zoukankan      html  css  js  c++  java
  • 转: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

  • 相关阅读:
    宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 21 合并两个有序链表
    Java实现 LeetCode 21 合并两个有序链表
    Java实现 LeetCode 21 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/cumtb3S/p/1758369.html
Copyright © 2011-2022 走看看