0

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

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

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

  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 个字节是完全发送)?

感谢您的见解。

4

2 回答 2

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);

你去吧。

于 2013-03-07T08:31:26.210 回答
1

我想模拟一个坏连接,其中 2 个段一个接一个地发送

这不是一个“糟糕的联系”。对于任何 TCP 连接来说,这是一种完全合法的行为方式。如果接收软件不能正确处理它,它就没有正确编写。

假设前 4 个字节已完全发送

你不能这样假设。

于 2013-03-07T10:13:28.497 回答