编译环境:DEV C++
配置编译器
Windows 下 实现 Socket 编译需要 ws2_32.lib 这个库的支撑,所以我们编译前应该配置下编译器,具体配置步骤如下:
Tools -> Compiler Options
加入 -l 链接,如图所示:
实现的功能
服务器端与客户端可以互相自由给对方发送消息,无需在意接收与发送的顺序(利用线程实现)!可以实现加法运算。如需其它的功能,可以自行补充,如:实现四则运算、文件传输等。
服务器程序
/* Name: TCP Server Copyright: -lws2_32 Author: Lance# Date: 18/05/18 Description: TCP Server */#include <stdio.h> #include <winsock2.h> #include <windows.h> #include <string.h>#define PORT 8080 #define BUFSIZE 1 024/* 客户端Socket与发送缓冲 */SOCKET client;unsigned char SendBuf[BUFSIZE+1];enum{ NoConnection, Connected, }LinkStatus;/* 客户端连接状态监控线程 */DWORD WINAPI print_message(LPVOID arg){ while(1){ if(!LinkStatus){ printf(" 等待客户端连接 .... \r\n"); sleep(1); } } }/* 服务器发送消息线程 */DWORD WINAPI send_message(LPVOID arg){ while(1){ memset(SendBuf, 0, 1024); fgets(SendBuf, 1024, stdin); send(client, SendBuf, 1024, 0); } } int main(int argc, char* argv[]){ WSADATA wsaData; struct sockaddr_in sin_addr; struct sockaddr_in remoteAddr; unsigned char recvData[BUFSIZE+1]; int nAddrlen = sizeof(remoteAddr); unsigned int num_l, num_r; unsigned char sum_buf[100] = {0}; /* 线程标识 */ HANDLE pthread; /* 启动 WSA */ WORD sockVersion = MAKEWORD(2, 2); if (WSAStartup(sockVersion, &wsaData)){ perror("WSA boot failed!"); return -1; } /* 创建服务端套接字 */ SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (server == INVALID_SOCKET){ perror("socket error!"); return -1; } /* 配置 sin_addr */ sin_addr.sin_family = AF_INET; sin_addr.sin_port = htons(PORT); /* 可监听任意的地址 */ sin_addr.sin_addr.S_un.S_addr = INADDR_ANY; /* 监听指定的地址 */// sin_addr.sin_addr.S_un.S_addr = inet_addr("192.168.1.149"); /* 绑定 */ if (bind(server, (LPSOCKADDR)&sin_addr, sizeof(sin_addr)) == SOCKET_ERROR){ perror("bind error!"); return -1; } /* 监听 */ if (listen(server, 100) == SOCKET_ERROR){ perror("listen error!"); return -1; } puts("服务器成功启动"); /* 创建状态线程 */ CreateThread(NULL,0,print_message,NULL,0,NULL); /* 创建消息线程 */ pthread = CreateThread(NULL,0,send_message,NULL,0,NULL); while (1) { LinkStatus = NoConnection; client = accept(server, (SOCKADDR *)&remoteAddr, &nAddrlen); LinkStatus = Connected; if (client == INVALID_SOCKET) { perror("accept error!"); continue; } printf("客户端:%s 已连接\r\n", inet_ntoa(remoteAddr.sin_addr)); while(1){ /* 数据接收 */ memset(recvData, 0, sizeof(recvData)); int ret = recv(client, recvData, 1024, 0); if (ret > 0){ printf("Recv: %s", recvData); /* 实现加法运算,客户端发来 "%d + %d =" 形式的数据后,将结果返回至客户端 */ if(sscanf(recvData, "%d + %d =", &num_l, &num_r) == 2){ sprintf(sum_buf, "%d + %d ,sum is %d", num_l, num_r, num_l + num_r); send(client, sum_buf, sizeof(sum_buf), 0); memset(sum_buf, 0, sizeof(sum_buf)); } }else /* 客户端异常则断开当前连接 */ goto Reconnect; /* 客户端要求退出的话则断开当前连接 */ if(!strncmp(recvData, "quit", 4)) goto Reconnect; } Reconnect: closesocket(client); puts("*** 客户端已断开"); } /* 关闭服务器套接字 */ closesocket(server); WSACleanup(); return 0; }
客户端程序
/* Name: TCP Client Copyright: -lws2_32 Author: Lance# Date: 18/05/18 Description: TCP Client */#include <stdio.h> #include <winsock2.h> #include <Windows.h> #include <string.h> #define PORT 8080 #define BUFSIZE 1024unsigned char recvData[BUFSIZE+1] = {0}; /* 线程标识 */HANDLE pthread;DWORD WINAPI recv_message(LPVOID arg){ int res; while(1){ memset(recvData, 0, 1024); res = recv((SOCKET)arg, recvData, 1024, 0); if(res > 0) printf("Recv: %s", recvData); else{ printf("*** 服务器已退出(回车退出程序)"); return 0; } } } int main(int argc, char * argv[]) { unsigned char SendBuf[BUFSIZE+1] = {0}; WSADATA wsaData; SOCKADDR_IN addrServ; if(argc != 2){ puts("argc error"); puts("Usage: <client.exe> <ip addr>"); return -1; } /* 启动 WSA */ WORD sockVersion = MAKEWORD(2, 2); if (WSAStartup(sockVersion, &wsaData)){ perror("WSA boot failed!"); return -1; } /* 创建 socket */ SOCKET client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (client == INVALID_SOCKET){ perror("socket failed"); return -1; } /* 配置 socket */ addrServ.sin_family = AF_INET; addrServ.sin_port = htons(PORT); /* 配置服务器 IP */ addrServ.sin_addr.S_un.S_addr = inet_addr(argv[1]); /* 连接至服务器 */ int ret = connect(client,(SOCKADDR*)&addrServ,sizeof(SOCKADDR)); if (SOCKET_ERROR == ret){ perror("socket connect failed"); closesocket(client); WSACleanup(); return -1; } /* 创建工作线程 */ pthread = CreateThread(NULL,0 ,recv_message,(LPVOID)client,0,NULL); puts("客户端成功启动,输入'quit'关闭客户端"); while(1) { memset(SendBuf,0,sizeof(SendBuf)); fgets(SendBuf, 1024, stdin); ret = send(client, SendBuf, 1024, 0); if (SOCKET_ERROR == ret){ closesocket(client); exit(0); } /* 客户端退出 */ if(!strncmp(SendBuf, "quit", 4)) goto Disconnect; } Disconnect: closesocket(client); WSACleanup(); return 0; }
运行结果演示
打开 CMD,进入可执行文件所在目录
执行 server.exe 运行服务器;
启动另一个 CMD,执行 client.exe 127.0.0.1 运行客户端。
双方可进行通信,效果如图:
你的支持就是我的动力! 转载请注明出处,谢谢!
作者:Lance#
原文链接:https://www.cnblogs.com/GyForever1004/p/9082360.html