/*********************************************************************** Author: JMF* Version:1.0* BUG: 最大只允许同时64个客户端同时连接(WSA_MAXIMUM_WAIT_EVENTS)***********************************************************************/#include <winsock2.h>#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <assert.h>
#pragma comment(lib,"Ws2_32.lib")
#define SERVER_ADDR "192.168.168.152"#define PORT 3000#define MAX_CONNECT 5#define MSG_SIZE 1024
typedef struct tagOlData{OVERLAPPED ol;WSABUF wb;char buff[MSG_SIZE];DWORD dwRecv;DWORD dwFlag;}OlData,*pOlData;
typedef pOlData LPOldData;
SOCKET g_Socket[WSA_MAXIMUM_WAIT_EVENTS] = {0};WSAEVENT g_Event[WSA_MAXIMUM_WAIT_EVENTS] = {0};DWORD g_dwNum = 0;LPOldData g_OleData[WSA_MAXIMUM_WAIT_EVENTS] = {0};
DWORD WINAPI ThreadProc(LPVOID lpPara);
int main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) return EXIT_FAILURE; if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { WSACleanup( ); return EXIT_FAILURE; }SOCKET sock = socket(AF_INET,SOCK_STREAM,0);assert(sock != INVALID_SOCKET);sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDR);assert(0 == bind(sock,(const sockaddr*)&addr,sizeof(sockaddr_in)));listen(sock,MAX_CONNECT);
HANDLE hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,NULL);if(hThread == NULL){ assert(0); closesocket(sock); WSACleanup();}
while(1){ sockaddr_in addr; int len = sizeof(sockaddr_in); memset(&addr,0,len); SOCKET client = accept(sock,(sockaddr*)&addr,&len);
assert(client != INVALID_SOCKET);
printf("client[%s] establish connection .../n",inet_ntoa(addr.sin_addr)); printf("client port[%d].../n",ntohs(addr.sin_port)); g_OleData[g_dwNum] = new OlData; g_OleData[g_dwNum]->wb.len = MSG_SIZE; g_OleData[g_dwNum]->wb.buf = g_OleData[g_dwNum]->buff; g_OleData[g_dwNum]->dwFlag = 0; g_OleData[g_dwNum]->dwRecv = 0; g_OleData[g_dwNum]->ol.hEvent = g_Event[g_dwNum] = WSACreateEvent(); g_Socket[g_dwNum] = client; ++g_dwNum;
WSARecv(client, &(g_OleData[g_dwNum-1]->wb), 1, &(g_OleData[g_dwNum-1]->dwRecv), &(g_OleData[g_dwNum-1]->dwFlag), &(g_OleData[g_dwNum-1]->ol), NULL);}
closesocket(sock);WSACleanup();return 0;}
DWORD WINAPI ThreadProc(LPVOID lpPara){BOOL ret = FALSE;while(true){ int index = WSAWaitForMultipleEvents(g_dwNum, (const WSAEVENT*)g_Event, FALSE, 1000, FALSE); if(index == WSA_WAIT_FAILED || index == WSA_WAIT_TIMEOUT) continue; index = index - WSA_WAIT_EVENT_0; ret = WSAGetOverlappedResult(g_Socket[index], &(g_OleData[index]->ol), &(g_OleData[index]->dwRecv), FALSE, &(g_OleData[index]->dwFlag) );
if(ret) { if(g_OleData[index]->dwRecv > 0) { WSAResetEvent(g_OleData[index]->ol.hEvent); //将其置为无信号状态 g_OleData[index]->buff[g_OleData[index]->dwRecv] = '/0'; printf("recv data:[%s]/n",g_OleData[index]->buff);
send(g_Socket[index],"Received OK ...",strlen("Received OK ..."),0); g_OleData[index]->dwFlag = 0; g_OleData[index]->dwRecv = 0; memset(g_OleData[index]->buff,0,MSG_SIZE);
WSARecv(g_Socket[index], &g_OleData[index]->wb, 1, &g_OleData[index]->dwRecv, &g_OleData[index]->dwFlag, &g_OleData[index]->ol, NULL); } else //当g_OleData[index]->dwRecv == 0,表示该客户端断开连接 { printf("Client has been disconnect ... /n"); delete g_OleData[index]; g_Event[index] = g_Event[g_dwNum -1]; g_Socket[index] = g_Socket[g_dwNum - 1]; g_OleData[index] = g_OleData[g_dwNum - 1];
--g_dwNum; } }
else printf("WSARecv error .../n");}printf("Child thread has been end .../n");return 0;}