.net - Socket.Receive 在收到所有数据之前不会阻塞

标签 .net vb.net sockets

哎!

我正在尝试获取一个 ftp 文件列表,并且已经有一个小型库可以做到这一点。问题是 Socket.Receive() 函数在收到所有数据之前不会阻塞。当我在该行设置断点时,它会接收所有数据,但如果我不这样做,则只有 38 个字节(应该在 380 左右)。

这是代码:

While True
    Dim bytes As Integer = cSocket.Receive(buffer, buffer.Length, SocketFlags.None)
    mes += ASCII.GetString(buffer, 0, bytes)
    If bytes < buffer.Length Then
        Exit While
    End If
End While

正如我所说:如果断点设置在 .Receive 部分的行中,它会起作用。我可以使用一种解决方法来保证一个额外的循环,但这似乎很脏。有任何想法吗?

//编辑:所以让我添加更多信息。我不知道我会收到多少数据。该代码来自从 ftp 服务器接收数据的函数。我以为当消息以 CRLF 结尾时我可以停止,但我不能这样做,因为列出的每个文件之间都有一个 CRLF。例子:
file1.textCRLFfile2.txtCLRFfile3.txtCRLF

有时,当我调用接收时,即使有更多文件要列出,它也只会返回一个最后带有 CRLF 的文件。所以这种情况对我来说似乎不稳定。

最佳答案

在这种情况下,“所有数据”到底是什么意思?在套接字关闭之前,总是可以有更多的数据。网络堆栈不知道也不关心某些数据在逻辑上属于一起。它被分成不同大小的 IP 数据包(由 complex algorithms 确定)。

对于作为接收方的您来说,这意味着您将在收到数据时以 block 的形式获取数据。您需要继续调用Receive直到您知道您拥有所需的所有数据。

来自 MSDN documentation (强调我的):

If you are using a connection-oriented Socket, the Receive method will read as much data as is available, up to the number of bytes specified by the size parameter.



您在设置断点时看到不同行为的原因是,您实际上是在发送方发送数据时暂停您的应用程序。操作系统仍然会接收数据包并缓冲它们,直到某一点。标准缓冲区大小为 8192 字节,可以使用 ReceiveBufferSize 更改属性(property)。

代码

这如何转化为代码?假设您实际上知道需要接收多少数据,改进后的代码将如下所示:
Dim bytesRemaining As Integer = Buffer.Length
Dim sb As New StringBuilder
While bytesRemaining > 0
    Dim bytes As Integer = cSocket.Receive(Buffer,
                                           bytesRemaining, SocketFlags.None)
    bytesRemaining -= bytes
    sb.Append(ASCII.GetString(Buffer, 0, bytes))
End While
mes = sb.ToString()

循环中的条件消失了,因为如果我们没有收到很多字节,我们不想退出,我们想继续阅读。 bytesRemaining持续计数仍有多少字节要接收。

与您的问题无关,但我已替换 mesStringBuilder 的字符串连接.您可能会创建很多新字符串,所有(除了最后一个)都需要被垃圾收集。

关于.net - Socket.Receive 在收到所有数据之前不会阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16083893/

相关文章:

c# - 使用 linq to Entity 框架按日期读取最近插入的行

vb.net - 从 vb.net 中的字符串末尾仅删除一个换行符

vb.net - 在一行写多个句子

c - 如果不操纵它如何改变值(value)?

c - 为什么bind(socket binding)方法会在当前目录生成一个文件?

c# - 是否有一个 IEnumerable 实现只迭代一次它的源代码(例如 LINQ)?

Javascript 作为托管动态 .net 语言

.net - 如何以编程方式检查用户是否可以访问 SharePoint 网站?

VB.NET Switch 语句 GoTo 案例

node.js - 使用 React 和 Socket.io 的聊天应用程序在发送过多消息后挂起