C# - 执行 SslStream.Read 后如何知道 TcpClient 中剩余多少字节

Posted

技术标签:

【中文标题】C# - 执行 SslStream.Read 后如何知道 TcpClient 中剩余多少字节【英文标题】:C# - How to know how many bytes are left in TcpClient after perform SslStream.Read 【发布时间】:2022-01-12 15:51:24 【问题描述】:

我正在做一个客户端-服务器应用程序,服务器将检查何时有数据可用 (TcpClient.Available > 0) 可供读取,但是当它运行 SslStream.Read 时,即使我知道我需要多少字节读取时,它仍然将 TcpClient.Available 设置回 0 并保留已读取的字节......我的代码未读取,因为条件 (TcpClient.Available > 0) 将是错误的,因此服务器不会对附加内容执行任何操作字节,直到客户端发送更多字节,这是不想要的,服务器应尽快处理客户端发送的所有字节。 这是一些代码:

static void main()

    TcpClient tcpClient = listener.AcceptTcpClient();
    SslStream s = new SslStream(tcpClient.GetStream(), false);
    //authenticate etc ...
    while (true)
    
        if (tcpClient.Available > 0) // now this condition is false until
                                     // the client send more bytes
                                     // which is not wanted
            work(tcpClient);
    

    
static void work(TcpClient c)

    //client sent 50 bytes
    byte[] data = new byte[10];
    s.Read(data, 0, 10); // I know this is not guaranteed to read 10 bytes 
    //so I have a while loop to read until it receives all the byes, this line is just for example
    
    // do something with the 10 bytes I read, back to the while loop
 
  

我的“工作”实际上创建了一个新线程来完成工作并锁定该客户端直到工作完成,以便该客户端在工作完成之前不会调用工作

因为我知道运行“工作”需要多少字节,所以我只读取该字节数并解锁客户端,以便客户端可以再次“工作”

当然还有其他客户端也需要工作,这里我只是展示一个来演示问题

【问题讨论】:

读到Read读到0字节。 SSL 层在收到完整的 SSL 记录并验证其完整性之前不会返回任何明文。 您在这里所做的,在循环中检查可用,是一件非常糟糕的事情。这称为轮询。它要么消耗 CPU 资源,要么导致可怕的响应时间。试图平衡这两个问题是毫无意义的练习。 @HaroldMorgan 解释了你应该做什么。 @Llama “读取直到读取 0 个字节”,不正确。如果读取 0 个字节,则表示套接字已关闭。 @Jeroen 取决于流,没有办法知道下一次调用Read 是否会返回 0,所以你不能停止阅读 before 它返回0 如果您希望确保阅读所有内容。因此,您必须阅读 直到 它返回 0,表明流已按您所说的那样关闭。 【参考方案1】:

您通常不知道从流中读取还剩多少字节

但是您可以“在读取时”从流中读取,因为SslStream.Read 返回读取的字节数!

所以你的代码变成了简单的

while (s.Read(data, 0, 10) > 0)

    // do something with the bytes you've read

这是人们使用流的一般方式 - 在读取时按块读取它们。

您可以在我之前链接的文档的示例中看到它(还有更多!您应该明确地检查一下)

【讨论】:

您的示例不完整。因为您需要s.Read(..) 的结果才能知道您实际收到了多少字节。 你是对的,我链接的文档中的示例可以更好地解释整个过程,我只是试图表达“你应该如何使用流”的一般概念和提供了进一步研究问题的途径

以上是关于C# - 执行 SslStream.Read 后如何知道 TcpClient 中剩余多少字节的主要内容,如果未能解决你的问题,请参考以下文章

c#SslStream的read()函数如何知道何时返回0?

React context dispatch 状态改变后如何处理

VC6.0程序编译后如何为程序添加图标

maxscale在mariadb主从切换后如何处理event的状态-handle_events

maxscale在mariadb主从切换后如何处理event的状态-handle_events

分组后如何处理大型集合聚合?