上次的兩次面試,一位面試官認真的看了我的博客(十分感動),然後建議我好好複習下socket還有操作系統。感覺找工作好多都要求socket編程,於是我再預習複習一下。主要是當時這門課學校老師照本宣科,連代碼都不講,也很沒意思,學生混老師也混。下面切入正題吧,我今天就複習這麼多。
這是在WIN上創建socket,創建項目時使用win32控制檯,要注意linux上是沒有windows.h頭文件的,所以這麼寫是不可以的。
#include <iostream>
#include<Windows.h>
using namespace std;
int main(int argc,char* argv[])
{
//初始化動態鏈接庫
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//22是版本號,加載動態鏈接庫
int sock = socket(AF_INET, SOCK_STREAM, 0);//AF_INET指明調用TCP/IP協議,SOCK_STREAM是TCP的協議(相對於UDP來講)
cout << sock << endl;//打印句柄id,失敗返回負值
//失敗提示
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
closesocket(sock);//關閉連接
return 0;
}
創建TCP服務器主要是建立結構體saddr,它是sockaddr_in類的,並綁定端口,使用bind:
#include <iostream>
#include<Windows.h>
using namespace std;
int main(int argc,char* argv[])
{
//初始化動態鏈接庫
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//22是版本號,加載動態鏈接庫
int sock = socket(AF_INET, SOCK_STREAM, 0);//AF_INET指明調用TCP/IP協議,SOCK_STREAM是TCP的協議(相對於UDP來講)
cout << sock << endl;//打印句柄id,失敗返回負值
//失敗提示
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
//測試端口號
unsigned short port = 8080;
if (argc > 1)
{
port = atoi(argv[1]);
}
//創建TCP相關的結構體
sockaddr_in saddr;
saddr.sin_family = AF_INET;//使用TCP
saddr.sin_port = htons(port);//本地字節序轉網絡字節序
//X86架構是小端的而網絡字節流是大端的,
//Linux不一定,小型linux使用的也是和網路字節序一樣的話轉換也只是一個空的宏,
//這時候會可有可無,但考慮兼容性要求建議加上
saddr.sin_addr.s_addr = htonl(0);//這裏可以指定網卡,0是任意的意思
if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)//綁定端口號到上面創建的socket,並判斷是否成功
{
cout << "bind port " << port << " failed!" << endl;
return -2;
}
else
{
cout<< "bind port " << port << " success!" << endl;
}
closesocket(sock);//關閉連接
return 0;
}
可以看到,系統資源足夠是不會失敗的:
接下來是監聽listen和建立連接accept。我使用了telnet來測試,IP就是本機ip,可以使用ipconfig命令查看;端口號是之前設定的8080端口。代碼如下:
#include <iostream>
#include<Windows.h>
using namespace std;
int main(int argc,char* argv[])
{
//初始化動態鏈接庫
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//22是版本號,加載動態鏈接庫
int sock = socket(AF_INET, SOCK_STREAM, 0);//AF_INET指明調用TCP/IP協議,SOCK_STREAM是TCP的協議(相對於UDP來講)
cout << sock << endl;//打印句柄id,失敗返回負值
//失敗提示
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
//測試端口號
unsigned short port = 8080;
if (argc > 1)
{
port = atoi(argv[1]);
}
//創建TCP相關的結構體
sockaddr_in saddr;
saddr.sin_family = AF_INET;//使用TCP
saddr.sin_port = htons(port);//本地字節序轉網絡字節序
//X86架構是小端的而網絡字節流是大端的,
//Linux不一定,小型linux使用的也是和網路字節序一樣的話轉換也只是一個空的宏,
//這時候會可有可無,但考慮兼容性要求建議加上
saddr.sin_addr.s_addr = htonl(0);//這裏可以指定網卡,0是任意的意思
if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)//綁定端口號到上面創建的socket,並判斷是否成功
{
cout << "bind port " << port << " failed!" << endl;
return -2;
}
else
{
cout<< "bind port " << port << " success!" << endl;
}
listen(sock, 10);//監聽,接受連接;10是列表大小,套接字接收隊列的最大大小
//accept每調用一次隊列就會減少一個
int client = accept(sock, 0, 0);//不需要連接信息
cout << client << endl;
closesocket(sock);//關閉連接
return 0;
}
這是測試案例:
telnet 192.168.1.110 8080
返回結果如下:
如果要取得連接者的信息的話,得在accept中傳入相應的信息:
#include <iostream>
#include<ws2tcpip.h>
#include<Windows.h>
using namespace std;
int main(int argc, char* argv[])
{
//初始化動態鏈接庫
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//22是版本號,加載動態鏈接庫
int sock = socket(AF_INET, SOCK_STREAM, 0);//AF_INET指明調用TCP/IP協議,SOCK_STREAM是TCP的協議(相對於UDP來講)
cout << sock << endl;//打印句柄id,失敗返回負值
//失敗提示
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
//測試端口號
unsigned short port = 8080;
if (argc > 1)
{
port = atoi(argv[1]);
}
//創建TCP相關的結構體
sockaddr_in saddr;
saddr.sin_family = AF_INET;//使用TCP
saddr.sin_port = htons(port);//本地字節序轉網絡字節序
//X86架構是小端的而網絡字節流是大端的,
//Linux不一定,小型linux使用的也是和網路字節序一樣的話轉換也只是一個空的宏,
//這時候會可有可無,但考慮兼容性要求建議加上
saddr.sin_addr.s_addr = htonl(0);//這裏可以指定網卡,0是任意的意思
if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)//綁定端口號到上面創建的socket,並判斷是否成功
{
cout << "bind port " << port << " failed!" << endl;
return -2;
}
else
{
cout << "bind port " << port << " success!" << endl;
}
listen(sock, 10);//監聽,接受連接;10是列表大小,套接字接收隊列的最大大小
//accept每調用一次隊列就會減少一個
sockaddr_in caddr;
socklen_t len = sizeof(caddr);
int client = accept(sock, (sockaddr*)&caddr, &len);//取信息
cout << client << endl;
char* ip = inet_ntoa(caddr.sin_addr);
unsigned short cport = ntohs(caddr.sin_port);//網絡字節序轉本地字節序
cout << "client ip is " << ip << " port is " << cport << endl;
closesocket(sock);//關閉連接
return 0;
}
END