none
CreateIoCompletionPort函数关联监听socket与通信socket的区别 RRS feed

  • 问题

  • 在看MSDN的时候,发现在AcceptEx函数的使用Demo的下面有下面这段代码:

    #include <stdio.h>
    #include "winsock2.h"
    #include "mswsock.h"
    #include <windows.h>

    void main() {
      //----------------------------------------
      // Declare and initialize variables
      WSADATA wsaData;
      HANDLE hCompPort;
      LPFN_ACCEPTEX lpfnAcceptEx = NULL;
      GUID GuidAcceptEx = WSAID_ACCEPTEX;
      WSAOVERLAPPED olOverlap;
     
      SOCKET ListenSocket, AcceptSocket;
      sockaddr_in service;
      char lpOutputBuf[1024];
      int outBufLen = 1024;
      DWORD dwBytes;

      //----------------------------------------
      // Initialize Winsock
      int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
      if( iResult != NO_ERROR )
        printf("Error at WSAStartup\n");

      //----------------------------------------
      // Create a handle for the completion port
      hCompPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, (u_long)0, 0 );

      //----------------------------------------
      // Create a listening socket
      ListenSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
      if (ListenSocket == INVALID_SOCKET) {
        printf("Error at socket(): ListenSocket\n");
        WSACleanup();
        return;
      }

      //----------------------------------------
      // Associate the listening socket with the completion port
      CreateIoCompletionPort((HANDLE)ListenSocket, hCompPort, (u_long)0, 0);

      //----------------------------------------
      // Bind the listening socket to the local IP address
      // and port 27015
      hostent* thisHost;
      char* ip;
      u_short port;
      port = 27015;
      thisHost = gethostbyname("");
      ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);

      service.sin_family = AF_INET;
      service.sin_addr.s_addr = inet_addr(ip);  service.sin_port = htons(port);

      if ( bind( ListenSocket,(SOCKADDR*) &service, sizeof(service) )  == SOCKET_ERROR ) {
        printf("bind failed\n");
        closesocket(ListenSocket);
        return;
      }

      //----------------------------------------
      // Start listening on the listening socket
      if (listen( ListenSocket, 100 ) == SOCKET_ERROR) {
        printf("error listening\n");
      }
      printf("Listening on address: %s:%d\n", ip, port);

      //----------------------------------------
      // Load the AcceptEx function into memory using WSAIoctl.
      // The WSAIoctl function is an extension of the ioctlsocket()
      // function that can use overlapped I/O. The function's 3rd
      // through 6th parameters are input and output buffers where
      // we pass the pointer to our AcceptEx function. This is used
      // so that we can call the AcceptEx function directly, rather
      // than refer to the Mswsock.lib library.
      WSAIoctl(ListenSocket,
        SIO_GET_EXTENSION_FUNCTION_POINTER,
        &GuidAcceptEx,
        sizeof(GuidAcceptEx),
        &lpfnAcceptEx,
        sizeof(lpfnAcceptEx),
        &dwBytes,
        NULL,
        NULL);

      //----------------------------------------
      // Create an accepting socket
      AcceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      if (AcceptSocket == INVALID_SOCKET) {
        printf("Error creating accept socket.\n");
        WSACleanup();
        return;
      }

      //----------------------------------------
      // Empty our overlapped structure and accept connections.
      memset(&olOverlap, 0, sizeof(olOverlap));

      lpfnAcceptEx(ListenSocket,
        AcceptSocket,
        lpOutputBuf,
        outBufLen - ((sizeof(sockaddr_in) + 16) * 2),
        sizeof(sockaddr_in) + 16,
        sizeof(sockaddr_in) + 16,
        &dwBytes,
        &olOverlap);

      //----------------------------------------
      // Associate the accept socket with the completion port
      CreateIoCompletionPort((HANDLE)AcceptSocket, hCompPort, (u_long)0, 0);

      //----------------------------------------
      // Continue on to use send, recv, TransmitFile(), etc.,.
      //...

    }

    我有二个问题不明白:

    1, CreateIoCompletionPort函数关监听socket与通信socket的区别?

    2, 我们一般用一个循环等待连接的到来,这里是用什么机制实现等待连接的到来?


    xiao
    2011年3月6日 5:10

答案

  • 这里有一点让我想不明白的就是关联监听socket的作用是什么?

    --------------------------------------------------------------------

    将完成端口与监听套接字关联起来,就是当有客户调用connect/ConnectEx,WSAConnect();来连接的时候,完成端口得到事件通知,当然你必须得先传递一些Accept事件(非阻塞,不是调用accept()函数),就是接受客户连接的事件。类似的代码你可以参考下面的例子程序代码中的PostAccept()函数部分,它会先将监听套接字与完成端口关联起来,然后传递Accept操作。工作线程中GetQueuedCompletionStatus等待事件通知结果。
    http://blog.csdn.net/VisualEleven/archive/2010/12/21/6088590.aspx


    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.
    2011年3月8日 1:37
    版主

全部回复

  • CreateIoCompletionPort将套接字与完成端口的关联起来。因此在这个套接字上进行的任何重叠操作都将通过完成端口发出完成通知。

    在创建了完成端口、将一个或多个套接字与之相关联之后,我们就要创建若干个线程来处理完成通知。这些线程不断循环调用GetQueuedCompletionStatus ()函数等待并返回完成通知(也可以设置超时时间值)。当有完成通知到来时,应用程序可以读取相应的完成键,因此,完成键可用来给套接字传递一些内置的信息。


    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.
    2011年3月7日 6:21
    版主
  • 我不是要问怎样实现完成端口, 上面的代码中监听线程中没有while循环,这是怎样实现监听的,这点让我想不明白。 上面的代码中,完成端口关联了监听socket和通信socket,我们一般是关联通信socket,因为完成端口的原理是通过单句柄数据也就是完成键传递一次通信socket的信息,是通过CreateCompletionPort函数传到GetQueuedCompletionStatus中对应的完成键中,在WSARecv和WSASend中才能得到通信的socket句柄。 这里有一点让我想不明白的就是关联监听socket的作用是什么?
    xiao
    2011年3月7日 15:54
  • 这里有一点让我想不明白的就是关联监听socket的作用是什么?

    --------------------------------------------------------------------

    将完成端口与监听套接字关联起来,就是当有客户调用connect/ConnectEx,WSAConnect();来连接的时候,完成端口得到事件通知,当然你必须得先传递一些Accept事件(非阻塞,不是调用accept()函数),就是接受客户连接的事件。类似的代码你可以参考下面的例子程序代码中的PostAccept()函数部分,它会先将监听套接字与完成端口关联起来,然后传递Accept操作。工作线程中GetQueuedCompletionStatus等待事件通知结果。
    http://blog.csdn.net/VisualEleven/archive/2010/12/21/6088590.aspx


    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.
    2011年3月8日 1:37
    版主