2 回答

TA貢獻1872條經驗 獲得超4個贊
Socket編程首先要包含所需的頭文件Winsock2.h并工程中添加庫文件ws2_32.lib.
接著加載套接字庫所用函數是
WSAStartup( wVersionRequested, &wsaData ); 第一個參數代表的是所要加載的套接字庫的版本,第二個參數用于存儲返回的版本信息
wVersionRequested = MAKEWORD( 1, 1 );用MAKEWORD來設置版本號的值其中地位代表主版本號
TCP編程:
服務器端的編寫:
1. 創建套接字
SOCKET socketSrc = socket(AF_INET, SOCK_STREAM, 0);
第一個參數:指定地址族在1.1版本中只能使用AF_INET
第二個參數:指定套接字的類型在1.1版本中指定指定兩種一SOCK_STREAM流式套接字和SOCK_DREAM數據報套接字
第三個參數:指示所要使用的的協議,如果為0則自動選擇合適的協議(推薦)
2. 綁定套接字
bind(socketSrc, (SOCKADDR*)&addsrc, sizeof(SOCKADDR));
第一個參數:一個未綁定的的套接字
第二個參數:通過一個SOCKADDR結構體將一個地址分配給套接字
第三個參數:第二個參數的大小長度
SOCKADDR結構體: struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
第一個成員:sin_family地址族(這個參數不使用網絡字節序列,其他參數都是網絡字節序列)
第二個成員:sin_port指定要綁定的端口使用htons來轉換成網絡字節序列因為是無符號短整型
第三個成員:in_addr的結構體用來存放地址in_addr的結構如下
struct in_addr {
union {
struct S_un_b;
struct S_un_w;
u_long S_addr;
} S_un;
};
可以看出in_addr是一個包含一個聯合體的結構體,聯合體可以用來存放不同類型的數據但只存放一個數據,根據選擇不同而不同,我們的程序中選擇的是長整型的變量S_addr來存放一個地址需用htonl來轉換成為網絡字節序;
l htonl和htons區別是在于一個是將一個32位的主機字節序列轉換成32位的TCP/IP的網絡字節序一個則是16位
l inet_addr的用處是將一個點分制的IP地址字符串轉換為一個合適的 in_addr的變量。
l inet_ntoa將一個網絡地址轉換為標準的點分式地址格式的字符串
3. 監聽套接字:
listen(socketSrc, 5); //listen用于將一個已綁定但未連接的套接字對象設定成監聽模式等 到一個即將到來的連接
第二個參數:表示等待連接的最大長度,如果參數被設置為SOMAXCONN將被設成一個最大的可能值
4. 接受連接:
在一個被設置為監聽的套接字上允許一個連接,并返回一個已連接的新的套接字
SOCKET socketconn = accept(socketSrc, (SOCKADDR*)&addclient, &len);
第一個參數:一個被設置為監聽狀態的套接字;
第二個參數:一個SOCKADDR結構體用于保存請求連接的實體的地址,根據地址族的不同所創建的結構體不一樣
第三個參數:存儲地址的長度,此參數在調用accept函數前必須初始化,否則會導致調用失敗
5. 完成以上工作后通過recv和send函數來接收和發送數據
recv(socketconn, recvbuf, 100, 0);
第一個參數是一個已連接的套接字
第二個參數是用來存儲接收的數據的緩沖區地址
第三個參數表示緩沖區的大小
第四個參數指示接收的模式此處設為0
客戶端的編寫
6. 首先也是創建套接字
7. 然后在建立連接
connect(sockclient, (SOCKADDR*)&addsrc, sizeof(SOCKADDR));
第二個參數是要連接的地址,第三個參數則是地址的大小
UDP編程部分在簡單的多線程聊天室的編寫中詳細說明
他是基于無連接的協議
所以編寫服務器端時只要綁定了套接字后就可以開始傳送和接受數據,而客戶端則只需創建套接字就可以開始傳送和接收
同過 recvfrom和sendto函數來操作
使用closesocket(m_socket);關閉一個套接字,使用WSACleanup();來釋放套接字庫
- 2 回答
- 0 關注
- 1103 瀏覽
添加回答
舉報