【问题标题】:Should EndReceive ever return zero if the socket is still connected?如果套接字仍然连接,EndReceive 是否应该返回零?
【发布时间】:2014-11-04 17:01:24
【问题描述】:

我正在对套接字进行以下 BeginReceive 调用:

m_socket.BeginReceive(m_buffer, 0, m_buffer.Length, SocketFlags.Partial, this.ReceiveCallback, null);

在我的班级ReceiveCallback 我调用的函数

try {
    int bytesReadFromSocket = m_socket.EndReceive(ar);
    if(bytesReadFromSocket > 0) {
         // Do some processing
    }
}
finally {
   if(m_socket.Connected) m_socket.BeginReceive(m_buffer, 0, m_buffer.Length, SocketFlags.Partial, this.ReceiveCallback, null);
}

我遇到的问题是 EndReceive 返回零,但 m_socket.Connected 返回 true,所以我再次调用 BeginReceive。这发生在一个永远不会停止的紧密循环中。从文档中不清楚 EndReceive 何时返回零。我认为它仅在套接字关闭时发生,但这似乎不是真的。

那么问题来了,EndReceive 在什么情况下可以返回零?

【问题讨论】:

  • 看看这个。 stackoverflow.com/questions/3970825/… 好像除了这3种情况,它会返回0。
  • Levi,我已经看过那篇文章了。这与我要问的问题无关。我特别询问 EndReceive 的返回值,如果返回值为零意味着套接字上没有更多可用数据。

标签: c# sockets asynchronous


【解决方案1】:

Socket.EndReceive() 在一种特定情况下返回 0:远程主机已开始或确认正常关闭序列(例如,对于基于 .NET Socket 的程序,使用 SocketShutdown.SendSocketShutdown.Both 调用 Socket.Shutdown() )。

但是请注意,从技术上讲,在套接字最终关闭之前,它是“已连接”的。

您不应使用Connected 属性来确定是否从套接字发出另一个读取。相反,由于返回值 0 是专门保留的,表示将不再发送数据,因此您应该简单地检查 EndReceive() 的返回值,如果该值为正数(即非零),则再次调用 BeginReceive() .

【讨论】:

  • 谢谢。我在想,如果套接字没有从另一侧正确关闭,那么“Socket.Connected”可能不是再次调用 BeginReceive 的有效检查。事实上,如果服务器断开连接,听起来有时连接可能会卡住,但客户端不承认。
  • 我想这取决于你对“卡住”的定义。如果客户端无法确认关闭,但仍然关闭它的结束,或者只是退出进程而不清理,那么服务器仍然会看到调用完成回调,但是当你调用EndReceive()时,你会得到一个异常(表示连接已重置)而不是 0 返回值。无论哪种方式,服务器最终都会知道套接字不再连接。 :)
  • 我在 EndReceive 上没有得到异常,我只是得到一个零返回值,我认为零并不一定意味着有错误。如果 EndReceive 返回零,您会说客户端应该关闭 ReceiveCallback 中的套接字吗?
  • 返回值为0表示另一端叫shutdown。当它们完成发送数据时,每个端都应该关闭套接字(关闭)。每一端,一旦他们已经关闭了套接字并且已经完成了 0 字节的接收(在他们关闭他们的一端之前或之后),然后他们可以关闭套接字.
  • 这取决于你还剩下什么要做。如果您自己已经完成了数据发送,并且已经调用了Shutdown(SocketShutdown.Send),那么您此时关闭套接字。如果您仍有数据要发送,那么您只需在某处(例如,与您的连接状态一起存储的私有标志......在许多情况下,无论如何,一个已经保持某种连接状态)远程主机已经关闭,然后当您发送完毕,调用Shutdown(SocketShutdown.Both),然后关闭socket。
【解决方案2】:

有时我们正在测试 TCP 连接,忘记初始化缓冲区数组。当它为 null 或为空时,EndReceive() 将始终返回 0。我对此有一个愚蠢的经历。

【讨论】:

    猜你喜欢
    • 2018-06-10
    • 1970-01-01
    • 2014-06-15
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    • 1970-01-01
    • 2017-10-30
    相关资源
    最近更新 更多