2009-08-25 24 views
1

嘿,我正在使用WSAEventSelect進行套接字事件通知。到目前爲止,一切都很酷,像魅力一樣工作,但有一個問題。WSAEventSelect模型

客戶端是一個.NET應用程序,服務器是用Winsock C++編寫的。在.NET應用程序中,我使用TCP/IP的System.Net.Sockets.Socket類。當我調用Socket.Shutdown()和Socket.Close()方法時,我收到服務器中的FD_CLOSE事件,我很確定沒問題。好的,當我檢查傳遞給WSAEnumNetworkEvents的WSANETWORKEVENTS的iErrorCode時,會發生問題。我檢查一下這樣

if (listenerNetworkEvents.lNetworkEvents & FD_CLOSE) 
    { 
     if (listenerNetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0) 
     { 
      // it comes here 
      // which means there is an error 
      // and the ERROR I got is 
      // WSAECONNABORTED 
      printf("FD_CLOSE failed with error %d\n", 
       listenerNetworkEvents.iErrorCode[FD_CLOSE_BIT]); 
      break; 
     } 

     closesocket(socketArray[Index]); 
} 

但它無法與WSAECONNABORTED錯誤。爲什麼?

編輯:順便說一句,我在同一臺計算機上運行的客戶端和服務器,是因爲它的呢?當我這樣做時,我收到了FD_CLOSE事件:

server.Shutdown(SocketShutdown.Both); // in .NET C#, client code 

回答

2

我猜你是在緊接着調用Shutdown()然後Close()。這會給你所看到的症狀,因爲這是「關閉連接」。 Shutdown()確實啓動了一個正常的斷開連接(TCP FIN),但緊隨其後的Close()會中斷該連接,並向對端發送一個TCP RST數據包。順便說一句,關機(SocketShutdown.Both)調用也會關閉連接。

正確圖案是:

  1. 調用shutdown()被設置爲「寫」,這意味着我們將不被任何更多的數據發送到遠端對等體的方向的參數。這會導致堆棧發送TCP FIN數據包。

  2. 返回等待Winsock事件。當遠程節點也完成寫入時,它也會調用Shutdown(「寫入」),導致堆棧向您的機器發送一個TCP FIN數據包,並讓您的應用程序獲得FD_CLOSE事件。在等待時,您的代碼應該準備好繼續從套接字讀取,因爲遠程對等方可能仍在發送數據。

(請原諒上文的僞C#我不++說話.NET,只有溫度。)

兩個同齡人預計將使用此相同的關斷模式:每個人都講述其他當它完成寫入,然後等待接收遠程節點在關閉其套接字之前寫入的通知。

要實現的重要一點是,TCP是一種雙向協議:每一方都可以獨立發送和接收另一方。關閉套接字並不是一件好事。這就像與另一個人談話,但只是說話而不願聽。優雅的關機協議說:「我現在已經說完了,我要等到你離開之前不再說話。」