Winsock编程中select模型是个好东西,不用多线程的话这是个很好的选择。
MFC编程中,如果还是用简单的阻塞模型while(1)的话,很可能会发生界面未响应,变白down掉的情况。所以这个时候select模型就显得十分重要。
这是控制台下的Select模型的模板,MFC下的select请看下一篇文章
#include<winsock2.h>
#include<ws2tcpip.h>
#include<windows.h>
#include<stdio.h>
#include<conio.h>
#pragma comment(lib,"ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 27015
int _tmain()
{
WSADATA wsaData;
int iResult;
SOCKET SeverSocket = INVALID_SOCKET;
iResult = WSAStartup(MAKEWORD(2,2),&wsaData);
if(iResult != 0)
{
//WSAStartup failed!\r\n
return 1;
}
SeverSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if(SeverSocket == INVALID_SOCKET)
{
//socket failed!
WSACleanup();
return 1;
}
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(DEFAULT_PORT);
addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
iResult = bind(SeverSocket, (const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN));
if(iResult == SOCKET_ERROR)
{
//Bind failed!
closesocket(SeverSocket);
WSACleanup();
return 1;
}
iResult = listen(SeverSocket,SOMAXCONN);
if(iResult == SOCKET_ERROR)
{
//Listen failed!
closesocket(SeverSocket);
WSACleanup();
return -1;
}
//Tcp sever strting...
WSAEVENT Event = WSACreateEvent();
int iIndex = 0,i;
int iEventTotal = 0;
WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS];
SOCKET sockArray[WSA_MAXIMUM_WAIT_EVENTS];
WSAEventSelect(SeverSocket,Event,FD_ACCEPT);
eventArray[iEventTotal] = Event;
sockArray[iEventTotal] = SeverSocket;
iEventTotal++;
//处理网络事件
SOCKADDR_IN addrClient;
int addrClientlen = sizeof(SOCKADDR_IN);
char recvbuf[DEFAULT_BUFLEN] ;
int recvbuflen = DEFAULT_BUFLEN;
while(1)
{
//在所有时间对象上等待
iIndex = WSAWaitForMultipleEvents(iEventTotal, eventArray,FALSE, WSA_INFINITE,FALSE);
iIndex = iIndex - WSA_WAIT_EVENT_0;
for(i=iIndex; i<iEventTotal;i++)
{
iResult = WSAWaitForMultipleEvents(1, &eventArray[i],TRUE,1000,FALSE);
if(iResult =WSA_WAIT_FAILED || iResult == WSA_WAIT_TIMEOUT)
{
continue;
}
else
{
WSANETWORKEVENTS newevent;
WSAEnumNetworkEvents(sockArray[i],eventArray[i],&newevent);
if(newevent.lNetworkEvents & FD_ACCEPT) //handle FD_ACCEPT message
{
if(newevent.iErrorCode[FD_ACCEPT_BIT]==0)
{
if(iEventTotal>WSA_MAXIMUM_WAIT_EVENTS)
{
//too many link,ignore....
continue;
}
SOCKET AcceptSocket = accept(sockArray[i],(SOCKADDR FAR*)&addrClient,&addrClientlen);
//"接收到新的连接"
WSAEVENT newEvent1 = WSACreateEvent();
WSAEventSelect(AcceptSocket, newEvent1,FD_READ|FD_CLOSE|FD_WRITE);
eventArray[iEventTotal] = newEvent1;
sockArray[iEventTotal] = AcceptSocket;
iEventTotal++;
}
}
if(newevent.lNetworkEvents & FD_READ)
{
if(newevent.iErrorCode[FD_READ_BIT]==0)
{
//if data reach
memset(recvbuf,0,recvbuflen);
iResult = recv(sockArray[i],recvbuf,recvbuflen,0);
if(iResult>0)
{
//seccess, deal with the data
}
else
{
//recv failed
<span style="font-family: Arial, Helvetica, sans-serif;">closesocket(sockArray[i]);</span>
<span style="font-family: Arial, Helvetica, sans-serif;"></span>
}
}
}
if(newevent.lNetworkEvents & FD_CLOSE)
{
//closing currect connection
closesocket(sockArray[i]);
}
if(newevent.lNetworkEvents & FD_WRITE)
{
//do data send
}
}
}
}
}