我正在使用networkstream在网络上传递短字符串。
现在,在接收方,我遇到了一个问题:
通常我会这样阅读

  • 查看所有
  • 是否有可用数据
  • 获取可用数据计数
  • 将这么多字节读入缓冲区
  • 将缓冲区内容转换为字符串。

  • 在假定所有提供的方法都可以正常工作的代码中,看起来像这样:
    NetworkStream stream = someTcpClient.GetStream();
    while(!stream.DataAvailable)
        ;
    
    byte[] bufferByte;
    stream.Read(bufferByte, 0, stream.Lenght);
    AsciiEncoding enc = new AsciiEncoding();
    string result = enc.GetString(bufferByte);
    

    但是,MSDN表示NetworkStream.Length并未真正实现,并且在被调用时始终会引发Exception。
    由于传入的数据长度不同,因此我无法对期望的字节数进行硬编码(这也是魔数(Magic Number)反模式的情况)。

    问题:
    如果我无法准确计数可读取的字节数,那么如何正确地从流中读取数据,而又不冒NetworkStream.Read内的各种异常的风险?

    编辑:
    尽管提供的答案可以带来更好的总体代码,但我仍然想分享我遇到的另一个选择:
    TCPClient.Available给出可读取的字节。我知道必须有一种方法来计算自己收件箱中的字节数。

    最佳答案

    无法保证在连接的一侧对Read的调用将与另一侧对Write的调用匹配1-1。如果要处理可变长度的消息,则由决定由来向接收方提供此信息。

    一种常见的方法是首先确定您要发送的消息的长度,然后再发送该长度信息。在接收端,您首先要获得长度,然后知道要分配多大的缓冲区。然后,您可以循环调用Read,直到读取了正确的字节数为止。请注意,在您的原始代码中,您当前忽略了Read的返回值,该值告诉您实际读取了多少个字节。在一次调用和返回中,即使您要求的字节数超过1个,该值也可能低至1。

    另一种常见的方式是决定消息的“格式”,例如消息号1始终为32字节,具有X结构,消息号2则为51字节,具有Y结构。使用这种方法,而不是在发送消息之前先发送消息长度,而是发送格式信息,而是先发送“这里是类型为1的消息”,然后再发送消息。

    如果适用的话,另一种常见的方式是使用某种形式的哨兵-如果您的消息将永远不会包含一个带有0xff值的字节,那么您将扫描接收到的字节,直到收到一个0xff字节为止,然后再扫描该字节之前的所有内容。字节是您想要接收的消息。

    但是,无论您想做什么,无论是上述方法之一还是其​​他方法,都必须由您的发送方和接收方共同努力以允许接收方发现每条消息。

    我忘了说了,但是改变周围一切的另一种方法是-如果您想交换消息,并且不想做上述任何事情,然后切换到更高级的东西-例如WCF或HTTP或其他东西,这些系统已经在处理消息帧,然后您可以集中精力处理消息。

    关于c# - NetworkStream.Length替代,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23602323/

    10-10 21:24