Пример реализации модели портов завершения.
#include <iostream.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
void ErrorView();
DWORD WINAPI MainServThread(LPVOID CompletionPort);
SOCKET sock;
#define RECV 1001
#define SEND 1002
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[1024];
int IO_Type;
} io_str, * lp_io_str;
typedef struct
{
SOCKET Socket;
} io_handle_data, * lp_io_handle_data;
int main()
{
WSADATA wsaData;
if(!WSAStartup(0x0202,&wsaData))
{
HANDLE io_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
if(io_port != NULL)
{
SYSTEM_INFO SystemInfo;GetSystemInfo(&SystemInfo);
for(int i = 0; i < (int)SystemInfo.dwNumberOfProcessors ; i++)
{
HANDLE MainThread;
DWORD dwID;
if((MainThread = CreateThread(NULL,0,
MainServThread,
(LPVOID)io_port,0,
&dwID)) == NULL)
{cout<<"Error CreateThread"<<endl;return -1;}
CloseHandle(MainThread);
}
SOCKET sockList;
if((sockList = WSASocket(AF_INET,
SOCK_STREAM,0,
NULL,0,
WSA_FLAG_OVERLAPPED)) != INVALID_SOCKET)
{
SOCKADDR_IN InetAddr;
InetAddr.sin_family = AF_INET;
InetAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
InetAddr.sin_port = htons(4004);
if(bind(sockList,(PSOCKADDR)&InetAddr,sizeof(InetAddr)) != SOCKET_ERROR)
{
if(!(listen(sockList,SOMAXCONN)))
{
SOCKET Accept;
while(TRUE)
{
if ((Accept = WSAAccept(sockList,NULL,NULL,NULL,0)) != SOCKET_ERROR)
{
cout<<"Accept: "<<Accept<<endl;
lp_io_handle_data sock;
sock = (lp_io_handle_data)GlobalAlloc(GPTR,sizeof(io_handle_data));
if(sock)
{
sock->Socket = Accept;
if(CreateIoCompletionPort((HANDLE)Accept,io_port,(DWORD)sock,0) != NULL)
{
lp_io_str io_data;
if((io_data = (lp_io_str)GlobalAlloc(GPTR,sizeof(io_str))) != NULL)
{
ZeroMemory(&(io_data->Overlapped),sizeof(OVERLAPPED));
io_data->DataBuf.len = 1024;
io_data->DataBuf.buf = io_data->Buffer;
io_data->IO_Type = RECV;
DWORD dwRecv,dwFlags = 0;
if(WSARecv(Accept,
&(io_data->DataBuf),
1,&dwRecv,
&dwFlags,
&(io_data->Overlapped),
NULL) != SOCKET_ERROR)
{
cout<<"WSARecv..."<<endl;}
else
{if(WSAGetLastError() != ERROR_IO_PENDING)
{cout<<"Error WSARecv..."<<endl;ErrorView();return -1;}}
}else{cout<<"Error GlobalAlloc(2)"<<endl;}
}else{cout<<"Error CreateIoCompletionPort(2)"<<endl;}
}else{cout<<"Error GlobalAlloc"<<endl;}
}else{cout<<"Error WSAAccept..."<<endl;ErrorView();return -1;}
}//while(TRUE)
}else{cout<<"Error listen..."<<endl;ErrorView();}
}else{cout<<"Error bind..."<<endl;ErrorView();}
}else{cout<<"Error WSASocket..."<<endl;ErrorView();}
}else{cout<<"Error CreateIoCompletionPort..."<<endl;}
}else{cout<<"Error WSAStartup..."<<endl;ErrorView();}
WSACleanup();
return 0;
}
/*************************************************************/
//Iioie ii?oa caaa?oaiey
/*************************************************************/
DWORD WINAPI MainServThread(LPVOID CompletionPort)
{
HANDLE h_io_port = (HANDLE)CompletionPort;
DWORD dwBytes;
lp_io_str io_data;
lp_io_handle_data sock;
while(TRUE)
{
if(GetQueuedCompletionStatus(h_io_port,
&dwBytes,
(LPDWORD)&sock,
(LPOVERLAPPED *)&io_data,
INFINITE) == 0)
{cout<<"Error...(1)"<<endl;}
if(dwBytes == 0)
{
if(closesocket(sock->Socket) != SOCKET_ERROR)
{cout<<"closesocket: "<<sock->Socket<<endl;}
else{cout<<"error closesocket..."<<endl;ErrorView();}
GlobalFree(io_data);
GlobalFree(sock);
continue;
}
if(io_data->IO_Type == SEND)
{
cout<<"SEND: "<<io_data->Buffer<<endl;
}
if(io_data->IO_Type == RECV)
{
cout<<io_data->Buffer<<endl;
if(io_data->Buffer[0] == '0')
{
ZeroMemory(&(io_data->Overlapped),sizeof(OVERLAPPED));
ZeroMemory(&(io_data->Buffer),sizeof(1024));
io_data->DataBuf.len = 1024;
strcpy(io_data->Buffer,"ok");
io_data->DataBuf.buf = io_data->Buffer;
io_data->IO_Type = SEND;
DWORD dwSend;
if (WSASend(sock->Socket,
&(io_data->DataBuf),
1,&dwSend,0,
&(io_data->Overlapped),
NULL) == SOCKET_ERROR)
{if(WSAGetLastError()!= ERROR_IO_PENDING)
{cout<<"Error WSASend..."<<endl;ErrorView();return -1;}}
continue;
}//if
}
ZeroMemory(&(io_data->Overlapped),sizeof(OVERLAPPED));
ZeroMemory(&(io_data->Buffer),sizeof(1024));
io_data->DataBuf.len = 1024;
io_data->DataBuf.buf = io_data->Buffer;
io_data->IO_Type = RECV;
DWORD dwRecv,dwFlags = 0;
if(WSARecv(sock->Socket,
&(io_data->DataBuf),1,
&dwRecv,&dwFlags,
&(io_data->Overlapped),
NULL) == SOCKET_ERROR)
{if(WSAGetLastError()!= ERROR_IO_PENDING)
{cout<<"Error WSARecv..."<<endl;ErrorView();return -1;}}
}
return 0;
}
/*************************************************************/
//Ooieoey auaiaa ioeaie...
/*************************************************************/
void ErrorView()
{
LPVOID lpMsgBuf = NULL;
FormatMessage
(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
CharToOem((LPTSTR)lpMsgBuf,(LPTSTR)lpMsgBuf);
cout<<(LPCTSTR)lpMsgBuf<<endl;
LocalFree(lpMsgBuf);
}