Complete Routine的基本使用,下面是一个简单的例子
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define LISTEN_PORT 5080
#define BUFF_SIZE 256
void CALLBACK WorkerRoutine(DWORD error, DWORD bytes_transferred,
LPWSAOVERLAPPED overlapped,
DWORD inflags);
typedef struct
{
WSAOVERLAPPED overlapped;
DWORD recv_bytes;
SOCKET client_sock;
DWORD inflags;
WSABUF buff;
}SOCKINFO;
int main(void)
{
WSADATA wsaData;
int nRet;
SOCKET listen_sock;
SOCKADDR_IN listen_addr;
SOCKET client_sock;
SOCKADDR_IN client_addr;
int client_addr_len = sizeof(client_addr);
char buff[BUFF_SIZE];
DWORD recv_bytes = 0;
int index;
SOCKINFO sockInfo;
WSAEVENT wsaEvent;
nRet = WSAStartup(MAKEWORD(2,2), &wsaData);
if(0 != nRet)
{
printf("WSAStartup() failed, error:%d.\n", WSAGetLastError());
return 1;
}
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(INVALID_SOCKET == listen_sock)
{
printf("socket() failed, error:%d.\n", WSAGetLastError());
goto retflag1;
}
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listen_addr.sin_port = htons(LISTEN_PORT);
nRet = bind(listen_sock, (SOCKADDR*)&listen_addr, sizeof(listen_addr));
if(nRet == SOCKET_ERROR)
{
printf("bind() failed, error:%d.\n", WSAGetLastError());
closesocket(listen_sock);
goto retflag1;
}
nRet = listen(listen_sock, 5);
if(SOCKET_ERROR == nRet)
{
printf("listen() failed, error:%d.\n", WSAGetLastError());
closesocket(listen_sock);
goto retflag1;
}
client_sock = accept(listen_sock, (SOCKADDR*)&client_addr, &client_addr_len);
if(INVALID_SOCKET == client_sock)
{
printf("accept failed, error:%d.\n", WSAGetLastError());
closesocket(listen_sock);
goto retflag1;
}
sockInfo.inflags = 0;
memset(&sockInfo.overlapped, 0, sizeof(sockInfo.overlapped));
sockInfo.client_sock = client_sock;
sockInfo.buff.buf = buff;
sockInfo.buff.len = BUFF_SIZE;
sockInfo.overlapped.hEvent = (HANDLE)&sockInfo;
if(WSARecv(client_sock, &sockInfo.buff, 1, &sockInfo.recv_bytes, &sockInfo.inflags, &sockInfo.overlapped, WorkerRoutine) == SOCKET_ERROR)
{
if(WSAGetLastError() == WSA_IO_PENDING)
{
printf("WSARecv() WSA_IO_PENDING.\n");
}
else
{
printf("WSARecv failed, error:%d.\n", WSAGetLastError());
closesocket(listen_sock);
closesocket(client_sock);
goto retflag1;
}
}
wsaEvent = WSACreateEvent();
if(WSA_INVALID_EVENT == wsaEvent)
{
printf("WSACreateEvent() failed, error:%d.\n", WSAGetLastError());
closesocket(listen_sock);
closesocket(client_sock);
goto retflag1;
}
while(1)
{
index = WSAWaitForMultipleEvents(1, &wsaEvent, FALSE, WSA_INFINITE, TRUE);
if(index = WAIT_IO_COMPLETION)
{
continue;
}
else
{
printf("WSAWaitForMultipleEvents() failed, error:%d.\n", WSAGetLastError());
closesocket(listen_sock);
closesocket(client_sock);
WSACloseEvent(wsaEvent);
goto retflag1;
}
}
closesocket(listen_sock);
closesocket(client_sock);
WSACloseEvent(wsaEvent);
retflag1:
nRet = WSACleanup();
if(0 != nRet)
{
printf("WSACleanup() failed, error:%d.\n", WSAGetLastError());
return 1;
}
return 0;
}
void CALLBACK WorkerRoutine(DWORD error, DWORD bytes_transferred,
LPWSAOVERLAPPED overlapped,
DWORD inflags)
{
SOCKINFO* sockInfo = NULL;
if(error != 0)
{
printf("Callback error:%d.\n", error);
return;
}
if(bytes_transferred == 0)
{
printf("peer closed.\n");
return;
}
sockInfo = (SOCKINFO*)overlapped->hEvent;
printf("%s", sockInfo->buff.buf);
sockInfo->inflags = 0;
memset(&sockInfo->overlapped, 0, sizeof(sockInfo->overlapped));
sockInfo->overlapped.hEvent = (HANDLE)sockInfo;
if(WSARecv(sockInfo->client_sock, &sockInfo->buff, 1, &sockInfo->recv_bytes, &sockInfo->inflags, &sockInfo->overlapped, WorkerRoutine) == SOCKET_ERROR)
{
if(WSAGetLastError() == WSA_IO_PENDING)
{
printf("WSARecv() WSA_IO_PENDING.\n");
}
else
{
printf("WSARecv failed, error:%d.\n", WSAGetLastError());
return;
}
}
}