完成端口GetQueuedCompletionStatus后,我怎么知道是WSASend完成了?还是WSARecv完成了??
//关键项typedef struct
{
   OVERLAPPED Overlapped;
   WSABUF DataBuf;
   CHAR Buffer[DATA_BUFSIZE];
   DWORD BytesSEND;
   DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct 
{
   SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
假如我前面代码中WSASend和WSARecv都投递了
下面代码看不懂
      //完成端口有消息来了
      if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
         (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
      {
         printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
         return 0;
      }
      //是不是有client退出了
      if (BytesTransferred == 0)
      {
          //.....
        continue;
       }
//下面看不懂
  if (PerIoData->BytesRECV == 0)
      {
         PerIoData->BytesRECV = BytesTransferred;
         PerIoData->BytesSEND = 0;
      }
      else
      {
         PerIoData->BytesSEND += BytesTransferred;
      }      if (PerIoData->BytesRECV > PerIoData->BytesSEND)
      {
         ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
         PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
         PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;

解决方案 »

  1.   

    re:我怎么知道是WSASend完成了?还是WSARecv完成了??
    ->
    通常的办法是在PER_IO_OPERATION_DATA里面加一个变量 指明投递前的 类型. 
    如, int type; //0 for recv, 1 for send
    那么你在投递WSASend 前 应该置type为1. 这样当你收到完成通知, 可以根据type来获知是send或recv.http://www.codeproject.com/internet/    有很多完成端口的例子. 对此有详细的代码加以说明了.====你那个看不懂的代码 , 它的意图是服务器收到多少字节就在send多少字节, 所以它根据收到的字节数BytesRECV 是否为0 来判断之前投递的是读操作, 或写操作.
      

  2.   

    PerIOData->OPCode == IOCP_OP_SEND 表示发送
    PerIOData->OPCode == IOCP_OP_RECV 表示接收
    PerIOData->OPCode ==  IOCP_OP_ACCEPT
      

  3.   

    漏了
    typedef struct
    {
    OVERLAPPED     Overlapped;
    IOCP_OP_CODE   OPCode;
             ...
    }PER_IO_OP_DATA, *LP_PER_IO_OP_DATA;
      

  4.   

    我想单独开个线程,在其中轮询服务器本地信息并主动发给客户端。我想不应该在此线程中再调用GetQueuedCompletionStatus了吧?但是如果不调用的话,我又如何得到本来是通过GetQueuedCompletionStatus的到的客户端信息?如socket(下面代码中的PerHandleData->Socket)。做个列表维护起来?
    还有这个CompletionKey:SendPerIoData,我是把它定义为全局变量的。没办法,要线程间共用。不知道大家怎么处理?? if (WSASend(PerHandleData->Socket, &(SendPerIoData->DataBuf), 1, &SendBytes, Flags,
      &(SendPerIoData->Overlapped), NULL) == SOCKET_ERROR)
      

  5.   

    我想单独开个线程,在其中轮询服务器本地信息并主动发给客户端。
    并且把这个发送代码放在里面,一取到数据我就发
     if (WSASend(PerHandleData->Socket, &(SendPerIoData->DataBuf), 1, &SendBytes, Flags,
      &(SendPerIoData->Overlapped), NULL) == SOCKET_ERROR)我的问题是PerHandleData->Socket这个参数不就是CLIENT socket吗!!还有SendPerIoData结构体(里面放WSAOVERLAPPED的那个) 都该如何存放??