/**********************************************************************
* 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;
}