Socket笔记

1、 为了增加效率,可以考虑采用无异常的函数
.net2.0Socket.Send,Socket.Receive 有了无异常的函数
Socket.Send(Byte[], Int32, Int32, SocketFlags, SocketError)
Socket.Receive(Byte[], Int32, Int32, SocketFlags, SocketError)
减少不必要的异常,就等于增加效率。

2Socket.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 状态。由于对方已关闭自己的套接字,所以不能再发送数据了。但应用程序却不同,它能一直发送数据,直到对方的套接字已关闭为止。

你可能感兴趣的:(socket)