WEB开发网
开发学院软件开发VC 用完成端口开发大响应规模的Winsock应用程序 阅读

用完成端口开发大响应规模的Winsock应用程序

 2007-03-17 22:00:47 来源:WEB开发网   
核心提示: 无论何时调用重叠操作函数时,总是会通过其lpOverlapped参数传递一个OVERLAPPEDPLUS结构(例如WSASend、 WSARecv等函数),用完成端口开发大响应规模的Winsock应用程序(3),这就允许你为每一个重叠调用操作设置某些操作状态信息,当操作结束后,如果重叠操作

无论何时调用重叠操作函数时,总是会通过其lpOverlapped参数传递一个OVERLAPPEDPLUS结构(例如WSASend、 WSARecv等函数)。这就允许你为每一个重叠调用操作设置某些操作状态信息,当操作结束后,你可以通过GetQueuedCompletionStatus()函数获得你自定义结构的指针。注意OVERLAPPED字段不要求一定是这个扩展后的结构的第一个字段。当得到了指向OVERLAPPED结构的指针以后,可以用CONTAINING_RECORD宏取出其中指向扩展结构的指针。

OVERLAPPED 结构的定义如下:

typedef struct _OVERLAPPEDPLUS {
  OVERLAPPED    ol;
  SOCKET      s, sclient;
  int        OpCode;
  WSABUF      wbuf;
  DWORD       dwBytes, dwFlags;
  // 其它有用的信息
} OVERLAPPEDPLUS;
#define OP_READ   0
#define OP_WRITE  1
#define OP_ACCEPT  2
下面让我们来看看工作者线程的情况。

工作线程WorkerThread代码:DWORD WINAPI WorkerThread(LPVOID lpParam)
{  
  ULONG_PTR    *PerHandleKey;
  OVERLAPPED   *Overlap;
  OVERLAPPEDPLUS *OverlapPlus,
          *newolp;
  DWORD      dwBytesXfered;
  while (1)
  {
    ret = GetQueuedCompletionStatus(
      hIocp,
      &dwBytesXfered,
      (PULONG_PTR)&PerHandleKey,
      &Overlap,
      INFINITE);
    if (ret == 0)
    {
      // Operation failed
      continue;
    }
    OverlapPlus = CONTAINING_RECORD(Overlap, OVERLAPPEDPLUS, ol);
  
  switch (OverlapPlus->OpCode)
  {
  case OP_ACCEPT:
    // Client socket is contained in OverlapPlus.sclient
    // Add client to completion port
      CreateIoCompletionPort(
        (HANDLE)OverlapPlus->sclient,
        hIocp,
        (ULONG_PTR)0,
        0);
    // Need a new OVERLAPPEDPLUS structure
    // for the newly accepted socket. Perhaps
    // keep a look aside list of free structures.
    newolp = AllocateOverlappedPlus();
    if (!newolp)
    {
      // Error
    }
    newolp->s = OverlapPlus->sclient;
    newolp->OpCode = OP_READ;
    // This function prepares the data to be sent
    PrepareSendBuffer(&newolp->wbuf);
 
    ret = WSASend(
        newolp->s,
        &newolp->wbuf,
        1,
        &newolp->dwBytes,
        0,
        &newolp.ol,
        NULL);
    
    if (ret == SOCKET_ERROR)
    {
      if (WSAGetLastError() != WSA_IO_PENDING)
      {
      // Error
      }
    }
    // Put structure in look aside list for later use
    FreeOverlappedPlus(OverlapPlus);
    // Signal accept thread to issue another AcceptEx
    SetEvent(hAcceptThread);
    break;
  case OP_READ:
    // Process the data read  
    // ...
    // Repost the read if necessary, reusing the same
    // receive buffer as before
    memset(&OverlapPlus->ol, 0, sizeof(OVERLAPPED));
    ret = WSARecv(
       OverlapPlus->s,
       &OverlapPlus->wbuf,
       1,
       &OverlapPlus->dwBytes,
       &OverlapPlus->dwFlags,
       &OverlapPlus->ol,
       NULL);
    if (ret == SOCKET_ERROR)
    {
      if (WSAGetLastError() != WSA_IO_PENDING)
      {
        // Error
      }
    }
    break;
  case OP_WRITE:
    // Process the data sent, etc.
    break;
  } // switch
  } // while
} // WorkerThread
其中每句柄键(PerHandleKey)变量的内容,是在把完成端口与套接字进行关联时所设置的完成键参数;Overlap参数返回的是一个指向发出重叠操作时所使用的那个OVERLAPPEDPLUS结构的指针。

要记住,如果重叠操作调用失败时(也就是说,返回值是SOCKET_ERROR,并且错误原因不是WSA_IO_PENDING),那么完成端口将不会收到任何完成通知。如果重叠操作调用成功,或者发生原因是WSA_IO_PENDING的错误时,完成端口将总是能够收到完成通知。

上一页  1 2 3 4 5 6 7 8  下一页

Tags:完成 端口 开发

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接