Socket向完成端口多次發送消息淺見

1.     同時發送多個WSARecv消息處理,多餘的會有什麼情況?

使用代碼測試,顯示結果爲全部返回錯誤997,表示都可以正常發出recv操作,且多個工作線程同時在檢測此socket的多個recv消息,運行片刻立即關閉Client端,發現工作線程出現的異常,1個或2個工作線程中的closesocket函數調用失敗,錯誤碼爲10038,因此要盡力避免對同一個socket向完成端口發送重複的同一信息。在接受數據時並沒有出現重複現象(內部有同步),也就是說只有在斷開socket時會有很小不出錯的可能,跟線程調度有關。

測試代碼如下:Server端:

(偵聽線程)

......

//成功與Client建立連接

while(1)
{

   while(WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
    &(PerIoData->Overlapped), NULL) ==SOCKET_ERROR && WSAGetLastError()    ==ERROR_IO_PENDING)
   {
    printf("WSARecv()2 failed with error %d/n", WSAGetLastError());

    Sleep(1000);
   }
   printf("WSARecv() succeed!/n");
   Sleep(5000);

}

......

 

(工作線程)

......

while(TRUE)
   {
      //完成端口有消息來了
      if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
         (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)//PerIoData的其他數據成員由此函數在收到數據時填充
      {
   if(GetLastError() ==64)//套接字無效,有人掉線了
   {
    printf("Invalid socket %d was closed!/n", PerHandleData->Socket);
    if(closesocket(PerHandleData->Socket) ==SOCKET_ERROR)
    {
     printf("closesocket() failed with error %d/n", WSAGetLastError());
     return 0;
    }
    GlobalFree(PerHandleData);
    GlobalFree(PerIoData);
    printf("PerIoData at %d was freed!/n", PerIoData);
    continue;
   }
      }
   printf("GetQueuedCompletionStatus() 返回BytesTransferred ==%d/n", BytesTransferred);//------

   printf("PerIoData->DataBuf.buf ==%s/n", PerIoData->DataBuf.buf);

   printf("completion routine running---------/n");

}

Client端:

......

//connect成功與Server取得鏈接

while(1)
 {

  //獲取鍵盤輸入,並保存
  cin>>lpPerIoData->Buffer;
  lpPerIoData->DataBuf.buf =lpPerIoData->Buffer;
  lpPerIoData->DataBuf.len =DATA_BUFSIZE;

  //發送數據
  if(WSASend(Client, &(lpPerIoData->DataBuf), 1, &(lpPerIoData->BytesSEND),
   0, &(lpPerIoData->Overlapped), NULL) ==SOCKET_ERROR)
  {
   printf("WSASend() failed with error %d/n", WSAGetLastError());
   Sleep(1000);
   return;
  }
  else
   printf("Send Succeed!/n");

   Sleep(5000);
 }

 Server打印信息見圖片。 

2.同時發送多個WSASend消息處理

由於是異步操作所以這個消息經常是立即成功返回0的,但是當完成端口內部的服務線程(不是指工作線程)有很多消息要處理的時候應該會返回997錯誤,因此WSASend消息是有可能被堆積在未完成消息隊列裏的,如果服務線程同時執行鍼對同一個socket的send操作"可能"(這裏是我猜的)會引起數據的混亂,因此不應重複調用WSASend發送消息。

3.同時發送WSARecv和WSASend消息

這兩者不衝突。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章