之前用c++实现过基于windows socket的单线程TCP服务器(http://www.cnblogs.com/jzincnblogs/p/5170230.html),今天实现了一个多线程的版本,可以接受多个客户端的请求,原理与之前的单线程版本相似,只是在多线程版本中主线程用于监测客户端请求,每当有新客户端请求连接,主线程便新开一个线程用户处理客户端的请求。代码如下:
头文件:
1 #ifndef SERVER_H 2 #define SERVER_H 3 4 #include <Winsock2.h> 5 #include <windows.h> 6 7 #pragma comment (lib, "ws2_32.lib") 8 9 #define IP_BUF_SIZE 129 10 11 class Server 12 { 13 public: 14 Server(); 15 ~Server(); 16 Server(const Server &) = delete; 17 Server & operator=(const Server &) = delete; 18 void WaitForClient(); 19 private: 20 WORD winsock_ver; 21 WSADATA wsa_data; 22 SOCKET sock_svr; 23 SOCKET sock_clt; 24 HANDLE h_thread; 25 SOCKADDR_IN addr_svr; 26 SOCKADDR_IN addr_clt; 27 int ret_val; 28 int addr_len; 29 char buf_ip[IP_BUF_SIZE]; 30 }; 31 32 #endif
函数定义:
1 #include "server.h" 2 #include <iostream> 3 #include <WS2tcpip.h> 4 5 using std::cerr; 6 using std::cout; 7 using std::endl; 8 9 #define SERVER_PORT 5000 10 #define MSG_BUF_SIZE 1024 11 12 Server::Server() 13 { 14 cout << "Initializing server...\n"; 15 // 16 winsock_ver = MAKEWORD(2, 2); 17 addr_len = sizeof(SOCKADDR_IN); 18 addr_svr.sin_family = AF_INET; 19 addr_svr.sin_port = ::htons(SERVER_PORT); 20 addr_svr.sin_addr.S_un.S_addr = ADDR_ANY; 21 memset(buf_ip, ‘\0‘, IP_BUF_SIZE); 22 // 23 ret_val = WSAStartup(winsock_ver, &wsa_data); 24 if (ret_val != 0) 25 { 26 cerr << "WSA failed to start up!Error code: " << ::WSAGetLastError() << "\n"; 27 system("pause"); 28 exit(1); 29 } 30 cout << "WSA started up successfully...\n"; 31 // 32 sock_svr = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 33 if (sock_svr == INVALID_SOCKET) 34 { 35 cerr << "Failed to create server socket!Error code: " << ::WSAGetLastError() << "\n"; 36 ::WSACleanup(); 37 system("pause"); 38 exit(1); 39 } 40 cout << "Server socket created successfully...\n"; 41 // 42 ret_val = ::bind(sock_svr, (SOCKADDR*)&addr_svr, addr_len); 43 if (ret_val != 0) 44 { 45 cerr << "Failed to bind server socket!Error code: " << ::WSAGetLastError() << "\n"; 46 ::WSACleanup(); 47 system("pause"); 48 exit(1); 49 } 50 cout << "Server socket bound successfully...\n"; 51 // 52 ret_val = ::listen(sock_svr, SOMAXCONN); 53 if (ret_val == SOCKET_ERROR) 54 { 55 cerr << "Server socket failed to listen!Error code: " << ::WSAGetLastError() << "\n"; 56 ::WSACleanup(); 57 system("pause"); 58 exit(1); 59 } 60 cout << "Server socket started to listen...\n"; 61 // 62 cout << "Server started successfully..." << endl; 63 } 64 65 Server::~Server() 66 { 67 ::closesocket(sock_svr); 68 ::closesocket(sock_clt); 69 ::WSACleanup(); 70 cout << "Socket closed..." << endl; 71 } 72 73 DWORD WINAPI CreateClientThread(LPVOID lpParameter); 74 // 75 void Server::WaitForClient() 76 { 77 while (true) 78 { 79 sock_clt = ::accept(sock_svr, (SOCKADDR*)&addr_clt, &addr_len); 80 if (sock_clt == INVALID_SOCKET) 81 { 82 cerr << "Failed to accept client!Error code: " << ::WSAGetLastError() << "\n"; 83 ::WSACleanup(); 84 system("pause"); 85 exit(1); 86 } 87 ::InetNtop(addr_clt.sin_family, &addr_clt, buf_ip, IP_BUF_SIZE); 88 cout << "A new client connected...IP address: " << buf_ip << ", port number: " << ::ntohs(addr_clt.sin_port) << endl; 89 h_thread = ::CreateThread(nullptr, 0, CreateClientThread, (LPVOID)sock_clt, 0, nullptr); 90 if (h_thread == NULL) 91 { 92 cerr << "Failed to create a new thread!Error code: " << ::WSAGetLastError() << "\n"; 93 ::WSACleanup(); 94 system("pause"); 95 exit(1); 96 } 97 ::CloseHandle(h_thread); 98 } 99 } 100 101 DWORD WINAPI CreateClientThread(LPVOID lpParameter) 102 { 103 SOCKET sock_clt = (SOCKET)lpParameter; 104 char buf_msg[MSG_BUF_SIZE]; 105 int ret_val = 0; 106 int snd_result = 0; 107 do 108 { 109 memset(buf_msg, ‘\0‘, MSG_BUF_SIZE); 110 ret_val = ::recv(sock_clt, buf_msg, MSG_BUF_SIZE, 0); 111 if (ret_val > 0) 112 { 113 if (strcmp(buf_msg, "exit") == 0) 114 { 115 cout << "Client requests to close the connection..." << endl; 116 break; 117 } 118 cout << "Message received: " << buf_msg << endl; 119 snd_result = ::send(sock_clt, buf_msg, MSG_BUF_SIZE, 0); 120 if (snd_result == SOCKET_ERROR) 121 { 122 cerr << "Failed to send message to client!Error code: " << ::GetLastError() << "\n"; 123 ::closesocket(sock_clt); 124 system("pause"); 125 return 1; 126 } 127 } 128 else if (ret_val == 0) 129 { 130 cout << "connection closed..." << endl; 131 } 132 else 133 { 134 cerr << "Failed to receive message from client!Error code: " << ::GetLastError() << "\n"; 135 ::closesocket(sock_clt); 136 system("pause"); 137 return 1; 138 } 139 } while (ret_val > 0); 140 // 141 ret_val = ::shutdown(sock_clt, SD_SEND); 142 if (ret_val == SOCKET_ERROR) 143 { 144 cerr << "Failed to shutdown the client socket!Error code: " << ::GetLastError() << "\n"; 145 ::closesocket(sock_clt); 146 system("pause"); 147 return 1; 148 } 149 return 0; 150 }
程序入口:
1 #include "server.h" 2 3 int main() 4 { 5 Server svr; 6 svr.WaitForClient(); 7 system("pause"); 8 return 0; 9 }
c++下基于windows socket的多线程服务器(基于TCP协议)
原文:http://www.cnblogs.com/jzincnblogs/p/5189636.html