转:SOCKET编程进阶之Overlapped I\O完成例程模型

SOCKET编程进阶之Overlapped I\O完成例程模型


原文地址:http://blog.csdn.net/echoff/archive/2007/09/23/1797319.aspx


完成例程模型相比与事件通知模型有个很大的优点就是不再受64个消息的限制,一个线程可以同时管理成百上千个socket连接,且保持较高的性能。
完成例程相比与完成端口较为逊色,因为它的性能不能随着系统CPU数量的增长而线程增长,不过在我看来已经很强了,呵呵~!
说白了,这些连接都是由系统来帮你管理的。你只需做的一件事就是:开启一个线程来accept进来的连接,剩下的工作交由系统来处理。而你,则需要提供给系统一个回调函数,发生新的网络事件的时候系统将执行这个函数:
procedure WorkerRoutine( const dwError, cbTransferred : DWORD; const lpOverlapped : LPWSAOVERLAPPED; const dwFlags : DWORD ); stdcall;
然后告诉系统用WorkerRoutine函数处理接收到的数据:
WSARecv( m_socket, @FBuf, 1, dwTemp, dwFlag, @m_overlap, WorkerRoutine );
然后......没有什么然后了,系统什么都给你做了!

 

代码
   
     
#pragma comment(lib,"ws2_32.lib")
#include
< winsock2.h >
#include
< stdio.h >
#define DATA_BUFSIZE 1024 // 接收缓冲区大小
#define MAXSESSION 10000 // 最大连接数
typedef
struct _SOCKET_INFORMATION {
OVERLAPPED Overlapped;
SOCKET Socket;
WSABUF DataBuf;
DWORD BytesSEND;
DWORD BytesRECV;
} SOCKET_INFORMATION,
* LPSOCKET_INFORMATION;

SOCKET ListenSocket
= INVALID_SOCKET;
DWORD Flags
= 0 ; // WSARecv的参数
void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred,LPWSAOVERLAPPED Overlapped, DWORD InFlags);
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(
2 , 2 ), & wsaData);
ListenSocket
= WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,NULL,WSA_FLAG_OVERLAPPED);
SOCKADDR_IN ServerAddr;
ServerAddr.sin_family
= AF_INET;
ServerAddr.sin_addr.S_un.S_addr
= htonl(INADDR_ANY);
ServerAddr.sin_port
= htons( 1234 );
bind(ListenSocket,(LPSOCKADDR)
& ServerAddr, sizeof (ServerAddr));
listen(ListenSocket,
100 );
printf(
" listenning...\n " );
SOCKADDR_IN ClientAddr;
int addr_length = sizeof (ClientAddr);
while (TRUE)
{
LPSOCKET_INFORMATION SI
= new SOCKET_INFORMATION;
if ((SI -> Socket = accept(ListenSocket,(SOCKADDR * ) & ClientAddr, & addr_length)) != INVALID_SOCKET)
{
printf(
" accept ip:%s port:%d\n " ,inet_ntoa(ClientAddr.sin_addr),ClientAddr.sin_port);
memset(
& SI -> Overlapped, 0 , sizeof (WSAOVERLAPPED));
SI
-> DataBuf.buf = new char [DATA_BUFSIZE];
SI
-> DataBuf.len = DATA_BUFSIZE;
memset(SI
-> DataBuf.buf, 0 ,DATA_BUFSIZE);
if (WSARecv(SI -> Socket, & SI -> DataBuf, 1 , & SI -> BytesRECV, & Flags, & SI -> Overlapped, WorkerRoutine) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf(
" disconnect\n " );
closesocket(SI
-> Socket);
delete [] SI
-> DataBuf.buf;
delete SI;
continue ;
}
}
}

}
return FALSE;
}
void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags)
{
LPSOCKET_INFORMATION SI
= (LPSOCKET_INFORMATION)Overlapped;
if (Error != 0 || BytesTransferred == 0 )
{
printf(
" disconnect\n " );
closesocket(SI
-> Socket);
delete [] SI
-> DataBuf.buf;
delete SI;
return ;
}
// 使用数据
printf( " call back:%s\n " ,SI -> DataBuf.buf);
memset(SI
-> DataBuf.buf, 0 ,DATA_BUFSIZE);

if (WSARecv(SI -> Socket, & SI -> DataBuf, 1 , & SI -> BytesRECV, & Flags, & SI -> Overlapped, WorkerRoutine) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf(
" disconnect\n " );
closesocket(SI
-> Socket);
delete [] SI
-> DataBuf.buf;
delete SI;
return ;
}
}
}
void main()
{
HANDLE hThreads
= CreateThread(NULL, 0 , AcceptThread, NULL, NULL, NULL);

WaitForSingleObject(hThreads,INFINITE);
printf(
" exit\n " );
CloseHandle(hThreads);
}


本文来自CSDN博客,转载请标明出处:http:
// blog.csdn.net/andylin02/archive/2008/10/12/3062724.aspx

 

 


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/andylin02/archive/2008/10/12/3062724.aspx

你可能感兴趣的:(socket编程)