1. 程式人生 > 實用技巧 >win32 | WinSock2網路程式設計 | socket-tcp通訊

win32 | WinSock2網路程式設計 | socket-tcp通訊

今天覆習了一下tcp通訊的實現,寫了寫程式碼。

簡單的總結一下

伺服器作為監聽者的角色需要先建立伺服器socket套接字,然後使用bind繫結套接字和埠資訊等等,再建立用於連線客戶端的socket套接字,使用accept函式等待客戶端的連線並處理。

客戶端則只需要建立用於連線伺服器的socket套接字connect函式建立與遠端主機的連結就可以了。

同時需要注意的是錯誤的處理關閉套接字等等。

伺服器:

  1 #include<WinSock2.h>
  2 #pragma comment(lib,"ws2_32.lib")
  3 #include <stdio.h>
  4
#include <string.h> 5 6 7 8 int main(){ 9 WSADATA wsaData; // 初始化返回資訊結構體 10 WORD wVersion = MAKEWORD(2,2); // 製作版本號 11 SOCKET hServer; // 定義套接字控制代碼 12 if (WSAStartup(wVersion, &wsaData)){ //初始化 13 printf("initial failed"); 14 return 0;
15 } 16 //in_addr addr; // ip地址結構體 17 //addr.s_addr = inet_addr("127.0.0.1"); // 轉化字串為32位整形ip地址 18 //char* lpszIp = inet_ntoa(addr); //整形轉化為字串形式 19 20 hServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //tcp形式流式套接字 21 if (hServer == INVALID_SOCKET){ 22 printf("socket failed \n
"); 23 } 24 sockaddr_in addrServer; 25 addrServer.sin_family = AF_INET; 26 addrServer.sin_port = htons(8888); // 指定埠 27 addrServer.sin_addr.s_addr = htonl(INADDR_ANY); //指定能訪問的ip 28 int nRet = bind(hServer, (sockaddr*)&addrServer, sizeof(addrServer)); 29 if (nRet == SOCKET_ERROR){ 30 printf("bind error \n"); 31 closesocket(hServer); 32 WSACleanup(); 33 return 0; 34 } 35 //進行監聽 36 nRet = listen(hServer,5); //最多監聽5個 37 printf("start listening ... \n"); 38 if (nRet == SOCKET_ERROR){ 39 printf("listen error \n"); 40 closesocket(hServer); 41 WSACleanup(); 42 return 0; 43 } 44 45 //接收客戶端請求 46 SOCKET hClient; 47 sockaddr_in addrClient; 48 int nLen = sizeof(addrClient); 49 hClient = accept(hServer,(sockaddr *)&addrClient, &nLen); // ?建立監聽控制代碼,直到接收到請求 50 if (hClient == INVALID_SOCKET){ 51 printf("accept error \n"); 52 closesocket(hServer); 53 WSACleanup(); 54 return 0; 55 } 56 printf("Get a connect! \n"); 57 send(hClient, "helllllllooooooo!!!!!!",sizeof("helllllllooooooo!!!!!!"), 0); 58 59 char szBuf[255]; 60 //迴圈接收客戶端資料 61 while (1) 62 { 63 memset(szBuf, 0, sizeof(szBuf)); // 清空緩衝區 64 nRet = recv(hClient, szBuf,sizeof(szBuf),0); 65 if (nRet == SOCKET_ERROR){ 66 printf("recv error \n"); 67 closesocket(hClient); 68 closesocket(hServer); 69 WSACleanup(); 70 return 0; 71 } 72 73 char sPrint[sizeof(szBuf)]; 74 sprintf(sPrint, "IP:%s, recv msg: %s ",inet_ntoa(addrClient.sin_addr),szBuf);//格式化字串 75 printf(sPrint); 76 if(strcmp(szBuf, "close") == 0){ // 檢測退出 77 nRet = send(hClient,"close",strlen("close"), 0); 78 break; 79 } 80 else{ 81 //接收到資料 82 sprintf(sPrint, "the server has recved your msg: %s ", szBuf); 83 nRet = send(hClient,sPrint,strlen(sPrint), 0); 84 if (nRet == SOCKET_ERROR){ 85 printf("send err \n"); 86 closesocket(hClient); 87 closesocket(hServer); 88 WSACleanup(); 89 return 0; 90 } 91 } 92 93 94 } 95 closesocket(hClient); 96 closesocket(hServer); 97 WSACleanup(); 98 99 return 0; 100 }

客戶端:

 1 #include<WinSock2.h>
 2 #pragma comment(lib,"ws2_32.lib")
 3 #include <stdio.h>
 4 #include <string.h>
 5 
 6 
 7 
 8 int main(){
 9     WSADATA wsaData;   // 初始化返回資訊結構體
10     WORD wVersion = MAKEWORD(2,2); // 製作版本號
11     SOCKET hClient;       // 定義套接字控制代碼
12     if (WSAStartup(wVersion, &wsaData)){       //初始化
13         printf("initial failed");
14         return 0;
15     }
16 
17     hClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //tcp形式流式套接字
18     if (hClient == INVALID_SOCKET){
19         printf("socket failed \n");
20     }
21 
22     sockaddr_in addrServer;
23     addrServer.sin_family = AF_INET;
24     addrServer.sin_port = htons(8888);     // 指定埠
25     addrServer.sin_addr.s_addr = inet_addr("192.168.56.101");               //指定要連線的ip
26     //建立連線
27     int nRet = connect(hClient,(sockaddr*)&addrServer, sizeof(addrServer));
28     if (nRet == SOCKET_ERROR){
29         printf("connect error \n");
30         closesocket(hClient);
31         WSACleanup();
32         return 0;
33     }
34     printf("connect successsssss!!!\n");
35 
36     char szBuf[255];
37     //迴圈接收客戶端資料
38     while (1)
39     {
40         memset(szBuf, 0, sizeof(szBuf)); // 清空緩衝區
41         nRet = recv(hClient, szBuf,sizeof(szBuf),0);
42         if (nRet == SOCKET_ERROR){
43             printf("recv error \n");
44             closesocket(hClient);
45             WSACleanup();
46             return 0;
47         }
48         
49         char sPrint[sizeof(szBuf)];
50         sprintf(sPrint, "recv msg: %s ",szBuf);//格式化字串
51         printf(sPrint);
52         if(strcmp(szBuf, "close") == 0){ // 檢測退出
53             nRet = send(hClient,"close",strlen("close"), 0);
54             break;
55         }
56         else{
57             //接收到資料
58             if (strcmp(szBuf, "helllllllooooooo!!!!!!") == 0){
59                 send(hClient, "wow", sizeof("wow"),0);
60             }
61         }
62         
63         
64     }
65     closesocket(hClient);
66     WSACleanup();
67     
68     return 0;
69 }