客户端:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include <winsock.h> 5 #include <process.h> 6 #pragma comment(lib,"ws2_32.lib") 7 8 #define port 5529 9 #define ip_addr "192.168.1.108" 10 11 //客户端写的线程 12 void write(void *p) 13 { 14 //指针类型转换 15 SOCKET client = (SOCKET)p; 16 while (1) 17 { 18 printf("请输入发送的信息: "); 19 char str[256] = { 0 }; 20 scanf("%s", str); 21 //发送 22 send(client, str, strlen(str), 0); 23 Sleep(100); 24 } 25 } 26 27 void main() 28 { 29 //对比版本 30 WSADATA WSA; 31 //客户端套接字 32 SOCKET client; 33 //服务器地址 34 struct sockaddr_in severaddr; 35 int addrlength = 0; 36 HANDLE hthread = NULL;//线程句柄 37 int Ret = 0;; 38 char senbuf[256] = { 0 }; 39 40 //对比版本 41 if (WSAStartup(MAKEWORD(2,2),&WSA)!=0) 42 { 43 puts("版本不一致,通信失败"); 44 system("pause"); 45 return; 46 } 47 //创建socket通信 48 client = socket(AF_INET, SOCK_STREAM, 0); 49 if (client == INVALID_SOCKET) 50 { 51 puts("客户端创建失败"); 52 system("pause"); 53 } 54 //设置服务器信息 55 //协议族 56 severaddr.sin_family = AF_INET; 57 //设置地址 58 severaddr.sin_addr.s_addr = inet_addr(ip_addr); 59 //设置端口 60 severaddr.sin_port = htons(port); 61 //清空 62 memset(severaddr.sin_zero, 0x00, 8); 63 64 //连接到服务器 65 Ret = connect(client, (struct sockaddr*) &severaddr, sizeof(severaddr)); 66 //判断是否连接成功 67 if (Ret!=0) 68 { 69 puts("客户端连接失败"); 70 system("pause"); 71 } 72 else 73 { 74 puts("客户端连接成功"); 75 } 76 77 //开启一个写的线程 78 _beginthread(write, 0, (void*)client); 79 //不断接收信息 80 while (1) 81 { 82 char receivebuf[256]; 83 memset(receivebuf, 0, 256);//清零 84 Ret = recv(client, receivebuf, 256, 0); 85 if (strlen(receivebuf)>0) 86 { 87 printf("%s ", receivebuf); 88 } 89 } 90 91 //关闭客户端 92 closesocket(client); 93 WSACleanup(); 94 }
服务器端
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include <winsock.h> 5 #include <process.h> 6 #pragma comment(lib,"ws2_32.lib") 7 8 //定义端口 9 #define port 5529 10 //设置本地ip 11 #define ip_addr "169.254.29.232" 12 //发送消息的缓存区 13 char sendbuf[256] = { 0 }; 14 //事件 15 HANDLE event=NULL; 16 //创建互斥量 17 HANDLE mutex = NULL; 18 19 //保存连接的客户端信息 20 struct ipinfo 21 { 22 SOCKET client;//客户端 23 struct sockaddr_in clientaddr; 24 }; 25 26 //读取线程是实时的,写入线程是有事件响应的,服务器输入或者收到消息则向客户端发送消息 27 28 //创建线程,用于向客户端发送信息 29 DWORD WINAPI clientwrite(void *p) 30 { 31 //数指针类型转换 32 SOCKET client = ((struct ipinfo*)p)->client; 33 //获取连接的客户端信息 34 struct sockaddr_in clientaddr = ((struct ipinfo*)p)->clientaddr; 35 int Ret = 0; 36 37 //不断读取 38 while (1) 39 { 40 //等待事件 41 WaitForSingleObject(event, INFINITE); 42 //创建互斥量 43 WaitForSingleObject(mutex, INFINITE); 44 //判断 45 if (strlen(sendbuf)!=0) 46 { 47 Ret = send(client, sendbuf, strlen(sendbuf), 0); 48 if (Ret == 0 || Ret == SOCKET_ERROR) 49 { 50 //判断连接的客户端是否退出 51 printf("%s,%d退出 ",inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port); 52 return; 53 } 54 } 55 ReleaseMutex(mutex); 56 ResetEvent(event);//手动复位 57 } 58 return 0; 59 } 60 61 //创建线程,用于读取客户端写入的信息 62 DWORD WINAPI clientthreadread(void *p) 63 { 64 //数指针类型转换 65 SOCKET client = ((struct ipinfo*)p)->client; 66 //获取连接的客户端信息 67 struct sockaddr_in clientaddr = ((struct ipinfo*)p)->clientaddr; 68 69 int Ret = 0; 70 //接收到的信息 71 char receivebufall[256] = {0}; 72 while (1) 73 { 74 75 char receivebuf[256] = { 0 }; 76 //接收 77 Ret = recv(client, receivebuf, 256, 0); 78 if (Ret == 0 ||Ret ==SOCKET_ERROR) 79 { 80 printf("%s,%d退出 ", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port); 81 return; 82 } 83 84 //收到 85 if (strlen(receivebuf) > 0) 86 { 87 memset(receivebufall, 0, 256); 88 sprintf(receivebufall, "收到%s:来自%s %d ", receivebuf, inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port); 89 printf("%s", receivebufall); 90 } 91 92 //互斥量修改全局数据 93 WaitForSingleObject(mutex, INFINITE); 94 memset(sendbuf, 0, 256); 95 strcpy(sendbuf, receivebufall); 96 ReleaseMutex(mutex); 97 //收到消息后设置事件,向所有客户端发送消息 98 SetEvent(event); 99 } 100 return 0; 101 } 102 103 //创建线程 104 //服务器 105 void mains(void *p) 106 { 107 //对比版本 108 WSADATA WSA; 109 //客户端 110 SOCKET client, sever; 111 //服务器地址,和连接的客户端信息 112 struct sockaddr_in localeaddr, clientaddr; 113 //sockaddr_in的结构体大小 114 int addrlength = 0; 115 //线程句柄 116 HANDLE hthread = NULL; 117 //发送和接收消息的返回值 118 int Ret = 0; 119 char senbuf[256] = { 0 }; 120 121 //判断版本 122 if (WSAStartup(MAKEWORD(2, 2), &WSA) != 0) 123 { 124 puts("版本不一致,通信失败 "); 125 system("pause"); 126 return; 127 } 128 //创建服务器套接字 129 sever = socket(AF_INET, SOCK_STREAM, 0); 130 if (sever == INVALID_SOCKET) 131 { 132 puts("服务器创建失败 "); 133 system("pause"); 134 return; 135 } 136 //设置本地的sockaddr_in 137 localeaddr.sin_family = AF_INET; 138 localeaddr.sin_addr.s_addr = inet_addr(ip_addr); 139 localeaddr.sin_port = htons(port); 140 memset(localeaddr.sin_zero, 0x00, 8);//清零 141 //socket与sockaddr_in绑定 142 Ret = bind(sever, (struct sockaddr*)&localeaddr, sizeof(localeaddr)); 143 if (Ret != 0) 144 { 145 puts("绑定失败"); 146 system("pause"); 147 return; 148 } 149 //开始监听 150 Ret = listen(sever, 5); 151 if (Ret != 0) 152 { 153 puts("监听失败"); 154 system("pause"); 155 return; 156 } 157 puts("服务器启动 "); 158 159 while (1) 160 { 161 //获取长度 162 addrlength = sizeof(clientaddr); 163 //通过套接字接受客户端连接 164 client = accept(sever, (struct sockaddr*) &clientaddr, &addrlength); 165 if (client == INVALID_SOCKET) 166 { 167 puts("接收失败"); 168 system("pause"); 169 return; 170 } 171 printf("客户端连接%s %d ", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port); 172 173 //全局变量pinfo只是起到一个中转的作用,最后结果存放在线程里面 174 //创建连接的客户端信息 175 struct ipinfo pinfo; 176 pinfo.client = client; 177 pinfo.clientaddr = clientaddr; 178 //开启一个写的线程 179 hthread = CreateThread(NULL, 0, clientwrite, (void*)&pinfo, 0, NULL); 180 //开启一个读的线程 181 hthread = CreateThread(NULL, 0, clientthreadread, (void*)&pinfo, 0, NULL); 182 } 183 184 closesocket(sever); 185 closesocket(client); 186 WSACleanup(); 187 } 188 189 190 191 void main() 192 { 193 event = CreateEvent(NULL, TRUE, FALSE, NULL); 194 mutex = CreateMutex(NULL, FALSE, NULL);//排斥 195 _beginthread(mains, 0, NULL); 196 while (1) 197 { 198 printf("请输入向客户端发送的信息:"); 199 scanf("%s", sendbuf); 200 SetEvent(event); 201 } 202 203 system("pause"); 204 }