WinSockAPI多线程服务器
运行效果:
程序:
// TcpServer.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <WinSock2.h> #include <Windows.h> #include <vector> #include <algorithm> using namespace std; //包含库 #pragma comment(lib, "ws2_32.lib") //发送最大字节数 #define MAXDATASIZE 100 #define BACKLOG 100 const int SERVERPORT = 9999; //连接数 static int connum; //客户端连接线程函数 DWORD WINAPI qtPingServerThreadFunc(LPVOID lpThreadParameter); //客户连接socket数组 vector<SOCKET> client_fd; int _tmain(int argc, _TCHAR* argv[]) { int err; SOCKET sockfd; struct sockaddr_in local_addr; struct sockaddr_in remote_addr; WORD wRequestVersion; WSADATA wsadata; wRequestVersion = MAKEWORD(2, 0); //启动socket服务 err = WSAStartup(wRequestVersion, &wsadata); if (0 != err) { printf("Socket Error!\n"); return 0; } if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wVersion) != 0) { WSACleanup(); printf("Version Wrong!\n"); return 0; } //创建socket sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == sockfd) { printf("Socket Create Failed!\n"); return 0; } else { printf("Socket Create Success!\n"); } //定义服务器地址信息 local_addr.sin_family = AF_INET; local_addr.sin_port = htons(SERVERPORT); //INADDR_ANY自动绑定地址 local_addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("172.16.254.212"); memset(&(local_addr.sin_zero), 0, 8); //绑定socket到本机地址 if (bind(sockfd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) == -1) { printf("bind wrong!\n"); return 0; } else { printf("bind success!\n"); } int n = 0; unsigned long ul = 1; while (1) { //主线程监听 if (listen(sockfd, BACKLOG) != -1) { printf("Listening...\n"); int sin_size = sizeof(struct sockaddr_in); //取出连接的客户端socket SOCKET sock = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size); //设置socket为非阻塞 ioctlsocket(sock,FIONBIO,(unsigned long *)&ul);// vector<SOCKET>::iterator itr_end = client_fd.end(); vector<SOCKET>::iterator itr = find(client_fd.begin(), itr_end, sock); if (itr == itr_end) { client_fd.push_back(sock); printf("receive a connection from %s\n", inet_ntoa(remote_addr.sin_addr)); connum++; printf("当前连接数:%d\n", connum); } DWORD dwPingThreadID; //创建新线程处理该客户socket连接 HANDLE hPingHandle = CreateThread(0, 0, qtPingServerThreadFunc, (LPVOID)sock, 0, &dwPingThreadID); } Sleep(50); } for (int i = 0 ; i < client_fd.size(); i++) { closesocket(client_fd[i]); } client_fd.clear(); WSACleanup(); return 0; } DWORD WINAPI qtPingServerThreadFunc(LPVOID lpThreadParameter) { SOCKET sock = (SOCKET)lpThreadParameter; int recvbytes; BYTE buf[MAXDATASIZE]; while (1) { //接收数据 recvbytes = recv(sock, (char *)buf, MAXDATASIZE, 0); //接收到的数据长度为0,则表示客户端主动断开连接 if (recvbytes == 0) { printf("disconnect!\n"); vector<SOCKET>::iterator itr_end = client_fd.end(); vector<SOCKET>::iterator itr = find(client_fd.begin(), itr_end, sock); if (itr != itr_end) { client_fd.erase(itr); } connum--; printf("当前连接数:%d\n", connum); return 0; } //接收信息,群发给所有客户端 else if ((recvbytes) != -1) { buf[recvbytes] = ‘\0‘; printf("Received: %s\n", buf); BYTE * head; head = buf; for (int i = 0; i < client_fd.size(); i++) { send(client_fd[i], (char *)buf, sizeof(buf), 0); } } Sleep(50); } return 0; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。