1、 為了增加效率,可以考慮采用無異常的函數
在.net2.0中Socket.Send,Socket.Receive 有了無異常的函數
Socket.Send(Byte[], Int32, Int32, SocketFlags, SocketError)
Socket.Receive(Byte[], Int32, Int32, SocketFlags, SocketError)
減少不必要的異常,就等于增加效率。
2、Socket.Connected 不是目前的Socket狀态
MSDN原文:擷取一個值,該值訓示 Socket 是在上次 Send 還是 Receive 操作時連接配接到遠端主機。
應當如何解決呢?
同樣MSDN也告訴了我們:
Connected 屬性的值反映最近操作時的連接配接狀态。如果您需要确定連接配接的目前狀态,請進行非阻止、零位元組的 Send 調用。
如果該調用成功傳回或引發 WAEWOULDBLOCK 錯誤代碼 (10035),則該套接字仍然處于連接配接狀态;否則,該套接字不再處于連接配接狀态。
3、要用Socket.Poll判斷是否可以接收,不要用Socket.Available
雖然Socket.Available可以偷窺到目前Recv緩沖區位元組數,而且Available是Poll速度的兩倍,但是MSDN說到:如果遠端主機使用 Shutdown 方法關閉了 Socket 連接配接,并且所有可用資料均已收到,則 Receive 方法将立即完成并傳回零位元組。
是以當網絡斷開的時候單純使用Socket.Available判斷是否recv到資料會存在不知道用戶端已經斷開Bug
補充:不推薦使用Socket.Poll對Socket的清單周遊,應當使用Socket.Select(或者其他模型),Socket.Poll是對Socket.Select的封裝,執行Socket.Poll耗時是非阻塞Socket.Recv的三倍。
4、非阻塞模式不能采用Receive的傳回值表示是否斷開
第3條說道:如果遠端主機使用 Shutdown 方法關閉了 Socket 連接配接,并且所有可用資料均已收到,則 Receive 方法将立即完成并傳回零位元組。但這并不能阻塞模式說明Socket已經斷開,這一條和C的recv函數不同,需要特别注意。需要判斷out出來的SocketError,當不為SocketError.Success、SocketError.Interrupted和SocketError.WouldBlock時就可以認為網絡已經斷開。
5、Send可能出現緩沖區滿的情況
判斷out出來的SocketError,如果等于SocketError.WouldBlock,則是Send緩沖區已滿,應斷開該Socket,否則影響整體速度,而不應當again, 反過來說允許的錯誤碼隻有SocketError.Interrupted,此時可以重來一次。
6、主動斷開Socket MSDN說道:如果目前使用的是面向連接配接的 Socket,則必須先調用 Shutdown 方法,然後才能關閉 Socket。這可以確定在已連接配接的套接字關閉之前,已發送和接收該套接字上的所有資料。
是以,網絡庫的Close函數可以封裝為先調用 Shutdown(SocketShutdown.Both),在調用Close()。
7、Socket已經關閉(Close)但不能在另一端斷開
一端Scoket已經關閉了,但另一端短時間内仍可以發送資料!這個問題還沒有找到解決辦法的,但原因已知,在《Windows網絡程式設計技術》一書(P139-P140)中說道:被動關閉的情況下,應用程式會從對方那裡接收一個FIN包,并用一個ACK包做出響應。此時,應用程式的套接字會變成ClOSE_WAIT狀态。由于對方已關閉自己的套接字,是以不能再發送資料了。但應用程式卻不同,它能一直發送資料,直到對方的套接字已關閉為止。