SslStream .read() returns 第一个字节一次数据包

SslStream .read() returns with first byte once a packet

我想从我的 SslStream 读取数据包。

我使用 websocket 发送数据包。另外,这个函数是在我完成 WS 握手后启动的,所以它是用来读取数据帧的。

这是阅读功能:

byte[] buffer = new byte[16 * 1024];
int read;
while (true) {
    read = input.Read(buffer, 0, buffer.Length);

    Console.WriteLine("Length: " + read + " Buffer: " + GetNumberOfSlotsUsed(buffer));

    if (read <= 0) {
        ...
    } else if (read < 3) {
        ...
    } else {
        ...
    }
}

一旦我收到一个数据包,这就是打印到控制台的内容:

Length: 1 Buffer: 1
Length: 57 Buffer: 57

问题可能出在这个函数中还是发送数据包的浏览器?

我用Java写的Websocket Server中的"socket.read()"函数没有问题,所以一定是C#吧?

编辑#1:

Java发送脚本代码:

var socket = new WebSocket(serviceUrl, protocol);
socket.onopen = function () {
    socket.send(omeString);
}

TCP 不允许 reader 确定发送的块大小。此信息不存在于写入中。您的应用程序协议必须能够处理数据可以并且将会以任意块到达的事实。

对于未来搜索此完全相同问题的人:

我找到一篇文章,解释说这种奇怪的情况是设计使然。

调用 "Feature." 似乎很奇怪 基本上(据我了解)此更改是使 SslStream 读取和写入第一个字节,然后推送其余字节。我个人认为这是一个奇怪的变化。强制传输多个数据包有点奇怪。 (我完全知道这可能会发生,在数据包可能被分段的可能性之上强制额外的数据包只是奇怪。)

Link to Article


发布者Nimbus.Hex

When ran on machine updated with KB3147458, this output is produced:
BytesRead => 1
BytesRead => 40
BytesRead => 1
BytesRead => 40
BytesRead => 1
BytesRead => 40
BytesRead => 1
BytesRead => 40
BytesRead => 1
BytesRead => 40

When ran on a machine without KB3147458, this output is produced:
BytesRead => 41
BytesRead => 41
BytesRead => 41
BytesRead => 41
BytesRead => 41

发布者Ilia Jerebtsov

I would guess that this is more specifically caused by KB3142037, which is a security update for MS16-065. The issues herein and a few workarounds are detailed at https://support.microsoft.com/en-us/kb/3155464 . There are registry keys that can be used to disable this "feature".


发布者微软:

Hi Nimbus.Hex, Yes Ilia is correct. This is a behavioral change done for security update for MS16-065. There are more details around the change available at https://support.microsoft.com/en-us/kb/3155464 . I resolving this as "By Design" Regards, Himadri

这是一个相当古老的问题,但我仍然愿意做出贡献。

如果您使用 Tls(准确地说是 TLS 1)对流进行身份验证,则会出现此问题。如果您遵循了 Microsoft 指南 (https://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx),您可能会使用以下代码进行身份验证。

stream.AuthenticateAsServer(serverCertificate,false, SslProtocols.Tls, false);

https://support.microsoft.com/en-us/kb/3155464 中所述,由于 TLS 1 中的漏洞,流将首先获得 1 个字节,然后是其余字节。为了解决这个问题,您的程序需要有一个标记来确定消息何时停止,例如 .

另一种方法是使用 TLS 1.2,您可以使用 stream.AuthenticateAsServer(serverCertificate,false, SslProtocols.Tls12, false);

使用这个你会得到完整的信息。