| 发表于:2007-04-25 14:14:44 楼主 |
#define port 5150 #define data_bufsize 8192 // 关键项 typedef struct { overlapped overlapped; wsabuf databuf; char buffer[data_bufsize]; dword bytessend; dword bytesrecv; } per_io_operation_data, * lpper_io_operation_data; typedef struct { socket socket; } per_handle_data, * lpper_handle_data; dword winapi serverworkerthread(lpvoid completionportid); void main( void ) { sockaddr_in internetaddr; socket listen; socket accept; handle completionport; system_info systeminfo; lpper_handle_data perhandledata; lpper_io_operation_data periodata; int i; dword recvbytes; dword flags; dword threadid; wsadata wsadata; dword ret; if ((ret = wsastartup( 0x0202 , & wsadata)) != 0 ) { printf( " wsastartup failed with error %d\n " , ret); return ; } // 打开一个空的完成端口 if ((completionport = createiocompletionport(invalid_handle_value, null, 0 , 0 )) == null) { printf( " createiocompletionport failed with error: %d\n " , getlasterror()); return ; } // determine how many processors are on the system. getsysteminfo( & systeminfo); // 开启cpu个数的2倍个的线程 for (i = 0 ; i < systeminfo.dwnumberofprocessors * 2 ; i ++ ) { handle threadhandle; // create a server worker thread and pass the completion port to the thread. if ((threadhandle = createthread(null, 0 , serverworkerthread, completionport, 0 , & threadid)) == null) { printf( " createthread() failed with error %d\n " , getlasterror()); return ; } // close the thread handle closehandle(threadhandle); } // 打开一个服务器socket if ((listen = wsasocket(af_inet, sock_stream, 0 , null, 0 , wsa_flag_overlapped)) == invalid_socket) { printf( " wsasocket() failed with error %d\n " , wsagetlasterror()); return ; } internetaddr.sin_family = af_inet; internetaddr.sin_addr.s_addr = htonl(inaddr_any); internetaddr.sin_port = htons(port); if (bind(listen, (psockaddr) & internetaddr, sizeof (internetaddr)) == socket_error) { printf( " bind() failed with error %d\n " , wsagetlasterror()); return ; } if (listen(listen, 5 ) == socket_error) { printf( " listen() failed with error %d\n " , wsagetlasterror()); return ; } // 开始接收从客户端来的连接 while (true) { if ((accept = wsaaccept(listen, null, null, null, 0 )) == socket_error) { printf( " wsaaccept() failed with error %d\n " , wsagetlasterror()); return ; } // 创建一个关键项用于保存这个客户端的信息,用户接收发送的重叠结构, // 还有使用到的缓冲区 if ((perhandledata = (lpper_handle_data) globalalloc(gptr, sizeof (per_handle_data))) == null) { printf( " globalalloc() failed with error %d\n " , getlasterror()); return ; } // associate the accepted socket with the original completion port. printf( " socket number %d connected\n " , accept); perhandledata -> socket = accept; // 与我们的创建的那个完成端口关联起来,将关键项也与指定的一个完成端口关联 if (createiocompletionport((handle) accept, completionport, (dword) perhandledata, 0 ) == null) { printf( " createiocompletionport failed with error %d\n " , getlasterror()); return ; } // 投递一次接收,由于接收都需要使用这个函数来投递一个接收的准备 if ((periodata = (lpper_io_operation_data) globalalloc(gptr, sizeof (per_io_operation_data))) == null) { printf( " globalalloc() failed with error %d\n " , getlasterror()); return ; } zeromemory( & (periodata -> overlapped), sizeof (overlapped)); periodata -> bytessend = 0 ; periodata -> bytesrecv = 0 ; periodata -> databuf.len = data_bufsize; periodata -> databuf.buf = periodata -> buffer; flags = 0 ; if (wsarecv(accept, & (periodata -> databuf), 1 , & recvbytes, & flags, & (periodata -> overlapped), null) == socket_error) { if (wsagetlasterror() != error_io_pending) { printf( " wsarecv() failed with error %d\n " , wsagetlasterror()); return ; } } } } // 工作线程 dword winapi serverworkerthread(lpvoid completionportid) { handle completionport = (handle) completionportid; dword bytestransferred; lpoverlapped overlapped; lpper_handle_data perhandledata; lpper_io_operation_data periodata; dword sendbytes, recvbytes; dword flags; while (true) { // 完成端口有消息来了 if (getqueuedcompletionstatus(completionport, & bytestransferred, (lpdword) & perhandledata, (lpoverlapped * ) & periodata, infinite) == 0 ) { printf( " getqueuedcompletionstatus failed with error %d\n " , wsagetlasterror()); return 0 ; } // 是不是有人退出了 if (bytestransferred == 0 ) { printf( " closing socket %d\n " , perhandledata -> socket); if (closesocket(perhandledata -> socket) == socket_error) { printf( " closesocket() failed with error %d\n " , wsagetlasterror()); return 0 ; } globalfree(perhandledata); globalfree(periodata); continue ; } // if (periodata -> bytesrecv == 0 ) { periodata -> bytesrecv = bytestransferred; periodata -> bytessend = 0 ; } else { periodata -> bytessend += bytestransferred; } if (periodata -> bytesrecv > periodata -> bytessend) { // post another wsasend() request. // since wsasend() is not gauranteed to send all of the bytes requested, // continue posting wsasend() calls until all received bytes are sent. zeromemory( & (periodata -> overlapped), sizeof (overlapped)); periodata -> databuf.buf = periodata -> buffer + periodata -> bytessend; periodata -> databuf.len = periodata -> bytesrecv - periodata -> bytessend; if (wsasend(perhandledata -> socket, & (periodata -> databuf), 1 , & sendbytes, 0 , & (periodata -> overlapped), null) == socket_error) { if (wsagetlasterror() != error_io_pending) { printf( " wsasend() failed with error %d\n " , wsagetlasterror()); return 0 ; } } } else { periodata -> bytesrecv = 0 ; // now that there are no more bytes to send post another wsarecv() request. flags = 0 ; zeromemory( & (periodata -> overlapped), sizeof (overlapped)); periodata -> databuf.len = data_bufsize; periodata -> databuf.buf = periodata -> buffer; if (wsarecv(perhandledata -> socket, & (periodata -> databuf), 1 , & recvbytes, & flags, & (periodata -> overlapped), null) == socket_error) { if (wsagetlasterror() != error_io_pending) { printf( " wsarecv() failed with error %d\n " , wsagetlasterror()); return 0 ; } } } } } |
|
|
|
|