IOCP服务端连接测试

来源:互联网 发布:java 颜色选择控件 编辑:程序博客网 时间:2024/05/03 00:06

用C写了个简单的IOCP服务端,该服务不做什么事情,仅仅做的事情就是接受客户端的连接。测试服务端最多支持的连接数。服务端代码,如下:

#include <stdio.h>#include <WinSock2.h>#include <Ws2tcpip.h>#pragma comment(lib, "ws2_32.lib")#define SVR_DATA_BUF_SIZE8000#define OP_READ1#define OP_WRITE2#define OP_ACCEPT3typedef struct{OVERLAPPEDoverlapped;WSABUFdatabuf;CHARbuffer[SVR_DATA_BUF_SIZE];int         nOp : 1;DWORDsend_bytes;DWORDrecv_bytes;} per_io_operation_data, *lp_per_io_operation_data;typedef struct{SOCKETsock;} per_data_key, *lp_per_data_key;volatile int iConnected = 0;DWORD WINAPI svr_worker_thread(LPVOID lpParam);int __cdecl main(void){WORD wVersionRequested;WSADATA wsaData;int err;SOCKET sckListener, sckAccepted;HANDLE hCompletionPort;SYSTEM_INFO system_info;struct sockaddr_in sagni, saclient;int iclientSize = sizeof(saclient);char hostname[NI_MAXHOST];char servinfo[NI_MAXSERV];char *ip = "127.0.0.1";u_short port = 2015;int backlog = 100;int i = 0;DWORD thread_id;u_long ul = 1;int optval = 1;LINGER lng;wVersionRequested = MAKEWORD(2,2);err = WSAStartup(wVersionRequested, &wsaData);if(err != 0){printf("WSAStartup failed with error:%d\n", err);return 1;}if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){printf("Could not find a usable version of winsock.dll\n");WSACleanup();return 1;}hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);if(hCompletionPort == NULL){printf("CreateIoCompletionPort() failed with error: %d\n", GetLastError());WSACleanup();return 1;}GetSystemInfo(&system_info);// create count of cpu * 2 + 1 threads.for(i = 0; i < system_info.dwNumberOfProcessors * 2 + 1; i++){HANDLE thread_handle = CreateThread(NULL, 0, svr_worker_thread, hCompletionPort, 0, &thread_id);if(thread_handle == NULL){err = GetLastError();printf("CreateThread() failed with error: %d\n", err);return 1;}CloseHandle(thread_handle);}sckListener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if(sckListener == INVALID_SOCKET){printf("socket() failed with error : %d\n", WSAGetLastError());WSACleanup();return 1;}sagni.sin_family = AF_INET;sagni.sin_addr.s_addr = inet_addr(ip);sagni.sin_port = htons(port);lng.l_linger = 0;lng.l_onoff = 1;setsockopt(sckListener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&optval, sizeof(optval));setsockopt(sckListener, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval));setsockopt(sckListener, SOL_SOCKET, SO_DONTLINGER, (char *)&optval, sizeof(optval));setsockopt(sckListener, SOL_SOCKET, SO_LINGER, (char *)&lng, sizeof(lng));err = bind(sckListener, (struct sockaddr *)&sagni, sizeof(struct sockaddr));if(err == SOCKET_ERROR){printf("bind() failed with error: %d\n", WSAGetLastError());closesocket(sckListener);WSACleanup();return 1;}err = listen(sckListener, backlog);if(err == SOCKET_ERROR){printf("listen() faield with error: %d\n", WSAGetLastError());closesocket(sckListener);WSACleanup();return 1;}printf("Listening...\n");while(1){HANDLE hWorkPort;DWORD recvBytes = 0, dwFlags = 0;lp_per_data_key key;lp_per_io_operation_data data;sckAccepted = accept(sckListener, (struct sockaddr *)&saclient, &iclientSize);if(sckAccepted == INVALID_SOCKET){printf("WSAAccept() failed with error: %d\n", WSAGetLastError());continue;}iConnected++;printf("%s:%d connected. %d\n", inet_ntoa(saclient.sin_addr), ntohs(saclient.sin_port), iConnected);if(ioctlsocket(sckAccepted, FIONBIO, (unsigned long *)&ul) == SOCKET_ERROR){printf("ioctlsocket() failed, info:%d\n", WSAGetLastError());closesocket(sckAccepted);continue;}key = (lp_per_data_key)GlobalAlloc(GPTR, sizeof(per_data_key));if(key == NULL){printf("GlobalAlloc() failed with error: %d\n", GetLastError());closesocket(sckListener);WSACleanup();return 1;}key->sock = sckAccepted;hWorkPort = CreateIoCompletionPort((HANDLE)sckAccepted, hCompletionPort, (DWORD)key, 0);if(hWorkPort == NULL){printf("CreateIoCompletionPort() failed with error: %d\n", GetLastError());closesocket(sckAccepted);continue;}data = (lp_per_io_operation_data)GlobalAlloc(GPTR, sizeof(per_io_operation_data));if(data == NULL){printf("GlobalAlloc() failed with error: %d\n", GetLastError());closesocket(sckListener);WSACleanup();return 1;}ZeroMemory(&(data->overlapped), sizeof(OVERLAPPED));data->send_bytes = 0;data->recv_bytes = 0;data->databuf.len = SVR_DATA_BUF_SIZE;data->databuf.buf = data->buffer;data->nOp = OP_READ;WSARecv(sckAccepted, &(data->databuf), 1, &recvBytes, &dwFlags, &(data->overlapped), NULL);} closesocket(sckListener);WSACleanup();return 0;}DWORD WINAPI svr_worker_thread(LPVOID lpParam){HANDLE hCompletionPort = (HANDLE)lpParam;DWORD bytesOfTransports;lp_per_data_keykey;lp_per_io_operation_data data;int err;DWORD dwThreadId = GetCurrentThreadId();while(TRUE){BOOL succ = GetQueuedCompletionStatus(hCompletionPort, &bytesOfTransports, (LPDWORD)&key, (LPOVERLAPPED *)&data, WSA_INFINITE);if(succ == 0){printf("GetQueuedCompletionStatus() failed with error: %d\n", GetLastError());closesocket(key->sock);GlobalFree(key);GlobalFree(data);continue;}if(bytesOfTransports == 0){iConnected--;printf("client socket was closed. %d\n", iConnected);closesocket(key->sock);GlobalFree(key);GlobalFree(data);continue;}switch(data->nOp){case OP_READ:{}break;case OP_WRITE:{}break;default:continue;}}}


然后使用Python写了个简单的客户端,该客户端唯一做的事情就是不断的连接服务器,并不发送和接收数据。代码如下:

import threadimport socketimport sysimport timehost = '127.0.0.1'port = 2015msgcount = 1000def thread_func(count):    socks = []    for i in range(0, count):        try:            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)        except:            print 'Cant create more socket.\n'            continue        try:            sock.connect((host, port))        except:            print 'Cant connect server.\n'            continue        socks.append(sock)    time.sleep(5)    for s in socks:        s.close()def main(c):    thread_func(c)if __name__ == "__main__":    main(int(sys.argv[1]))    input()

 

原创粉丝点击