-
2006-11-27
8.2.4 重叠模型 - [多线程程序设计]
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://xingzhesun.blogbus.com/logs/3921200.html
8.2.4 重叠模型
s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
1.事件通知 将win32事件对象与WSAOVERLAPPED结构关联在一起。
typedef struct WSAOVERLAPPED
{
DWORD Internal;
DWORD InternalHigh;
DWORD offset;
DWORD OffsetHigh;
WSAEVENT hEvent;
} WSAOVERLAPPED, FAR*LPWSAOVERLAPPED;
hEvent 它允许应用程序将一个事件对象句柄同一个套接字关联起来。BOOL WSAGetOverlappedResult(SOCKET S, LPWSAOVERLAPPED lpOverlapped, LPDWORD lpcbTransfer, BOOL fWari, LPDWORD lpdwFlags);
void main()
{
WSABUF DataBuf;
DWORD EventTotal = 0;
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED AcceptOverlapped;
SOCKET ListenSocket, AcceptSocket;//step 1
//start winsock and set up a listening socket//step 2
//accepte an inbound connectionAcceptSocket = accept(ListenSocket, NULL, NULL);
//step 3
//set up an overlapped structureEventArray[EventTotal]=WSACreateEvent();
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));AcceptOverlapped.hEvent = EventArray[EventTotal];
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;EventTotal++;
//step 4;
//post a WSARecv request to begin receiving data on the socket.
WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL);//Process overlapped receives on the socket.
while (TRUE)
{
//step 5
//wait for overlapped io call to complete
Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);//Index should be 0 because we have one event handle in eventarray.
//step 6
//reset the signaled event
WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);//step 7
//Determine the status of the overlapped request.
WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags);//First check to see whether the peer has closed the connection ,and if so , close the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", AcceptSocket);
closesocket(AcceptSocket);
WSACloseEvent(Index - WSA_WAIT_EVENT_0);
return;
}//Do something with the received data DataBuf contains the received data.
...//step 8
//post another WSARecv() request on the socket
Flags = 0;
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = Buffer;WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL);
}
}2.完成例程
在一个重叠IO请求完成时由系统调用的函数。他们的基本设计宗旨是通过调用者的线程,为一个已完成的I请求提供服务。除此之外,应用程序可通过完成例程,继续进行重叠IO处理。
void CALLBACK CompletionROUTINE(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);WSABUF DataBuf;
SOCKET AcceptSocket;void main()
{
WSAOVERLAPPED Overlapped;
//step 1
//start winsock and set up a listening socket//step 2
//accept a new connection
AcceptSocket = accept(ListenSocket, NULL, NULL);
//step 3
//To get the overlapped IO processing started, first submit an overlapped WSARecv() request.Flags = 0;
ZeroMemory(&Overlapped, sizeof(WSAOVERLAPPED));DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;EventTotal++;
//step 4;
//post a WSARecv request to begin receiving data on the socket.
if(WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, WorkerRoutine)==SOCKET_ERROR)
{
if (WSAGetLastError()!=WSA_IO_PENDING)
{
printf("WSARecv() failed with error%d\n",WSAGetLastError());
return;
}
}//since the WSAWaitForMutipleEvents()API requires waiting on one or more event objects, we will have to create a dummy event object, Aa
//an alterative , we can use SleepEx() instead.
EventArray[0]=WSACreateEvent();while (TRUE)
{
//step 5
Index = WSAWaitForMultipleEvents(1,EventArray, FALSE, WSA_INFINITE, FALSE);//step 6
if (Index == WAIT_IO_COMPLETION)
{
//An overlapped request completion routine just completed ,continue servicing more completion rountines.
}
else
{
//A bad error occurred --stop processing! if we were also processing an event object, this could be index to the event array.return;
}
}
}void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags)
{
DWORD SendBytes, RecvBytes;
DWORD Flags;
if (Error !=0)||BytesTransferred ==0
{
//Either a bad error occurred on the socket or the socket was closed by peer closesocket(AcceptSocket);
return;
}//At this point, an overlapped WSARecv() request completed successfully. Now we can retrieve the received data that is contained in the variable DataBuf
//After processing the received data, we need to post another overlapped WSARecv() or WSASend() request. For simplicity , we will post another WSARecv() requst.
Flags = 0;
ZeroMemory(&Overlapped,sizeof(WSAOVERLAPPED));DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = Buffer;if (WSARecv(AcceptSocket, &DataBuf,1,&RecvBytes,&Flags, &Overlapped, WorkerRoutine)==SOCKET_ERROR)
{
if (WSAGetLastError()!=WSA_IO_PENDING)
{
printf("failed with error%d\n",WSAGetLastError());
return;
}
}
}随机文章:
第一篇 上路吧,线程 2006-11-28第四章 命名管道 2006-11-19第三章 邮槽 2006-11-17第二章 重定向器 2006-11-16第一章 NetBIOS 2006-11-16
收藏到:Del.icio.us








