102.tcp實現多線程連接與群聊
阿新 • • 發佈:2018-02-28
多線程 scan accept hand 客戶端 ever 創建線程 自己的 簡單的
- 協議之間的關系
- socket在哪
- socket是什麽
Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把復雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。
門面模式,用自己的話說,就是系統對外界提供單一的接口,外部不需要了解內部的實現。
- socket編程的基本流程
tcp通信實現多線程連接與群聊
服務器端
- 定義端口以及本地ip地址
1 #define port 9876 2 #define ip_addr "192.168.1.102"
-
創建事件以及互斥量
1 HANDLE event;//事件 2 HANDLE mutex = NULL;
1 event = CreateEvent(NULL, TRUE, FALSE, NULL);//第二個參數TRUE表示手動復位 2 mutex = CreateMutex(NULL, FALSE, NULL);//互相排斥
-
接收連接
1 //接受連接 2 void recv_connect(void *p) 3 { 4 WSADATA WSA;//對比版本 5 6 SOCKET client,sever;//客戶端 7 8 //本地地址信息,以及連接的客戶端地址信息
-
向客戶端發送消息的多線程函數
1 //創建線程向客戶端發送消息 2 DWORD WINAPI clientthreadwrite(void *p) 3 { 4 SOCKET client = (SOCKET)p;//數指針類型轉換 5 int Ret = 0; 6 7 while (1) 8 { 9 WaitForSingleObject(event, INFINITE);//等待事件 10 WaitForSingleObject(mutex, INFINITE); 11 12 if (strlen(sendbuf) != 0) 13 { 14 //發送信息 15 Ret = send(client, sendbuf, strlen(sendbuf), 0); 16 } 17 ReleaseMutex(mutex); 18 ResetEvent(event);//手動復位 19 } 20 }
-
從客戶端接收消息的多線程函數
1 DWORD WINAPI clientthreadread(void *p) 2 { 3 //數指針類型轉換 4 SOCKET client = (SOCKET)p; 5 int Ret = 0; 6 char receivebuf[256]; 7 8 while (1) 9 { 10 //清零 11 memset(receivebuf, 0, 256); 12 //讀取 13 Ret = recv(client, receivebuf, 256, 0); 14 if (Ret == SOCKET_ERROR) 15 { 16 puts("客戶端send失敗"); 17 break; 18 } 19 printf("\n收到%s,", receivebuf); 20 //進入臨界區 21 WaitForSingleObject(mutex, INFINITE); 22 memset(sendbuf, 0, 256); 23 //全局變量,鎖定 24 strcpy(sendbuf, receivebuf); 25 ReleaseMutex(mutex); 26 //通知 27 SetEvent(event); 28 } 29 return 0; 30 }
- main函數
1 void main() 2 { 3 event = CreateEvent(NULL, TRUE, FALSE, NULL);//第二個參數TRUE表示手動復位 4 mutex = CreateMutex(NULL, FALSE, NULL);//互相排斥 5 6 _beginthread(recv_connect, 0, NULL); 7 8 Sleep(100); 9 while (1) 10 { 11 printf("請輸入要發送的信息:"); 12 scanf("%s", sendbuf); 13 SetEvent(event); 14 } 15 system("pause"); 16 }
客戶端
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include <winsock.h> 5 #pragma comment(lib,"ws2_32.lib") 6 7 //定義端口號 8 #define port 9876 9 //要連接的ip地址 10 #define ip_addr "192.168.1.102" 11 12 13 void main() 14 { 15 //對比版本 16 WSADATA WSA; 17 //客戶端套接字 18 SOCKET client; 19 //服務器信息 20 struct sockaddr_in severaddr; 21 //線程句柄 22 HANDLE hthread = NULL; 23 //保存連接信息 24 int Ret = 0; 25 char senbuf[256] = { 0 }; 26 27 if (WSAStartup(MAKEWORD(2,2),&WSA)!=0) 28 { 29 puts("版本不一致,通信失敗"); 30 system("pause"); 31 return; 32 } 33 //創建socket 34 client = socket(AF_INET, SOCK_STREAM, 0); 35 if (client == INVALID_SOCKET) 36 { 37 puts("客戶端創建失敗"); 38 system("pause"); 39 40 } 41 //設置服務器信息 42 severaddr.sin_family = AF_INET; 43 //設置地址 44 severaddr.sin_addr.s_addr = inet_addr(ip_addr); 45 //端口 46 severaddr.sin_port = htons(port); 47 //清空 48 memset(severaddr.sin_zero, 0x00, 8); 49 50 //連接 51 Ret = connect(client, (struct sockaddr*) &severaddr, sizeof(severaddr)); 52 if (Ret!=0) 53 { 54 puts("客戶端鏈接失敗"); 55 system("pause"); 56 } 57 while (1) 58 { 59 //printf("請輸入向服務器發送的消息:"); 60 //scanf("%s", senbuf);//輸入 61 //Ret = send(client, senbuf, strlen(senbuf), 0);//發送 62 //if (Ret==SOCKET_ERROR) 63 //{ 64 // puts("客戶端send失敗"); 65 // system("pause"); 66 //} 67 char receivebuf[256]; 68 memset(receivebuf, 0, 256);//清零 69 Ret = recv(client, receivebuf, 256, 0); 70 printf("收到客戶端發送的消息:%s\n", receivebuf); 71 } 72 73 closesocket(client); 74 WSACleanup(); 75 }
102.tcp實現多線程連接與群聊