• 转: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

  • 相关阅读:
    COGNOS10启动服务报错 问题解决
    Linux 下 新增Oracle10g 实例 (转自http://www.cnblogs.com/lan0725/archive/2011/07/18/2109474.html)
    WIN7安装COGNOS8后配置IIS网站后,访问COGNOS站点网页一直显示空白,解决方法(转载)
    Gridview光棒效果 鼠标滑过
    11款实用的一句话网站设计代码
    自定义js方法 (格式化时间)
    测试一下
    UTF7转换GB2312编码的方法(中文)
    HTML注册页面验证注册信息
    android欢迎页
  • 原文地址:https://www.cnblogs.com/cumtb3S/p/1758369.html
Copyright © 2020-2023  润新知