c# - 为什么在客户端拆分 TCP 消息不起作用?

标签 c# sockets tcp client-server

我使用 C# 编写了一个客户端-服务器应用程序。

客户端异步发送一个带有定义消息大小的 4 字节 header 的消息,服务器等待完整 消息(它知道大小)然后引发一个DataReceived 事件。当我异步发送和接收数据时,一切正常。

在某些时候我想模拟一个错误的连接,其中使用 Send() 而不是 BeginSend() 一个接一个地发送 2 个片段

  public void SendSyncString(string str, Commands cmd)
    {

        BinaryWriter bw = new BinaryWriter(new MemoryStream());
        bw.Write((int)cmd);
        bw.Write((int)str.Length);
        bw.Write(Encoding.ASCII.GetBytes(str));
        bw.Close();
        byte[] data = ((MemoryStream)(bw.BaseStream)).ToArray();
        bw.BaseStream.Dispose();
        SendSync(data,1);

    }

    public void SendSync(byte[] data,int delay)
    {
        //create |dataLength|data| segment
        byte[] dataWithHeader = Combine(BitConverter.GetBytes(data.Length), data);
        //send first block of data, delay, and then send the rest
        socket.Send(dataWithHeader, 0, 4, SocketFlags.None);
        Thread.Sleep(delay*1000);
        socket.Send(dataWithHeader, 5, dataWithHeader.Length - 5, SocketFlags.None);
    }

不起作用。我确实希望了解为什么。 如果我的 TCP 只是一个字节流,并且没有办法知道每个段何时到达, 为什么我不能按照我的意愿将它分成多个段,然后像上面那样简单地发送它们(假设前 4 个字节已完全发送)?

感谢您的见解。

最佳答案

因为您的第一个 socket.Send 调用只发送了 4 个字节:

socket.Send(dataWithHeader, 0, 4, SocketFlags.None);

也就是说,发送偏移量为 0、1、2 和 3 的字节(总共 4 个字节)。请记住 socket.Send 的第三个参数是长度参数,而不是结束位置。

因此,这一行有一个错误:

socket.Send(dataWithHeader, 5, dataWithHeader.Length - 5, SocketFlags.None);

它将字节从偏移量 5,6,7.. 发送到数组的末尾。 它跳过了第 4 个字节。因此,接收方可能会阻塞,因为它还差一个字节就可以接收到完整的消息。

它应该是:

socket.Send(dataWithHeader, 4, dataWithHeader.Length - 4, SocketFlags.None);

给你。

关于c# - 为什么在客户端拆分 TCP 消息不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15265800/

相关文章:

加载程序集后执行的 C# 方法

c# - 在 C# 中使用 IPv6 连接到 mySql 服务器

c# - 通过 C# 和 WinForms 开发自定义 GUI 设计器的架构和模式

windows - 将 Winsock 移植到 Linux 套接字

c++ - 如何在不同流程/系统中的 Rhapsody 模型之间进行通信?

java - 打开 tcp InetSocketAddress 到应用程序路径(不仅仅是主机 + 端口)

c - TCP 连接错误 "No buffer space available"

c# - 使用Xamarin表单选择产品时如何显示产品详细信息

c - TCP 客户端/服务器 : when stop read socket

c# - 如何确定哪个 EndPoint 导致错误代码 10054 的 SocketException? ("An existing connection was forcibly closed by the remote host.")