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

时间:2013-03-07 07:50:21

标签: c# sockets tcp client-server

我使用C#编写了一个Client-Server应用程序。

客户端异步发送一条消息,其中包含一个定义消息大小的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个字节是完全发送的)?

感谢您的见解。

2 个答案:

答案 0 :(得分: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);

你去。

答案 1 :(得分:1)

  

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

这不是'糟糕的联系'。对于任何TCP连接来说,这都是完全合法的方式。如果接收软件没有正确处理,则表明它没有正确写入。

  

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

你不能假设。