【问题标题】:Deserializing data sent via TCP反序列化通过 TCP 发送的数据
【发布时间】:2023-03-23 05:08:02
【问题描述】:

我在通过 TCPClient 发送对象时遇到问题。首先,我将它们序列化为字节数组,然后发送它们。 TCPListener 接收到一些数据,但反序列化器抛出异常“流的意外结束”。

这里是接收者代码:

    public void start()
    {
        TcpListener listener = new TcpListener(IPAddress.Any, 8090);
        listener.Start();

        while (true)
        {
            TcpClient client = listener.AcceptTcpClient();
            processClient(client);
        }
    }

    public void processClient(TcpClient client)
    {
        NetworkStream net = client.GetStream();


        ReadData(net);

        byte[] response  = Encoding.UTF8.GetBytes("Hello from the server.");
        net.Write(response, 0, response.Length);
        net.Close();
        client.Close();
    }

void ReadData(NetworkStream netstream)
{
    byte[] buffer = new byte[2048];
    System.IO.MemoryStream memStream = new System.IO.MemoryStream();

    netstream.ReadTimeout = 5000;

    int bytes = -1;

    while ((bytes = netstream.ReadByte()) != -1)
    {
        memStream.WriteByte((byte)bytes);
    }

    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bform = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();


    Packet packet = (Packet)bform.Deserialize(memStream);

    OnMessageArrived(this, new MessageEventArgs(packet.From.ToString(), packet.Data.ToString()));

    memStream.Close();
    netstream.Close();

}

这里是发件人代码:

    public void sendData(string to, Packet data)
    {
        TcpClient client = new TcpClient();

        MemoryStream mstream = new MemoryStream();

        client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090));
        if (client.Connected)
        {
            NetworkStream stream = client.GetStream();

            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bform = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            bform.Serialize(mstream, data);

            byte[] buffer = new byte[2048];
            mstream.Read(buffer, 0, buffer.Length);

            stream.Write(buffer, 0, buffer.Length);
            stream.Flush();
            stream.Close();
            client.Close();
        }
    }

发送方主方法:

    static void Main(string[] args)
    {
        SimplestTCPIP.Client client = new SimplestTCPIP.Client();

        Packet packet = new Packet("client", "server", IPAddress.Parse("127.0.0.1"));

        client.sendData("server", packet);

        Console.WriteLine("IP: " + GetIP().ToString());
        Console.Read();
    }

接收主方法:

    static void Main(string[] args)
    {
        SimplestTCPIP.Server server = new SimplestTCPIP.Server();

        server.OnMessageArrived += new SimplestTCPIP.Server.MessageArrived(server_OnMessageArrived);

        Thread thread = new Thread(server.start);
        thread.Start();

    }

    static void server_OnMessageArrived(object sender, SimplestTCPIP.Server.MessageEventArgs m)
    {
        Console.WriteLine(m.From + " : " + m.Text);
    }

【问题讨论】:

  • 你解决过这个问题吗?

标签: c# .net serialization tcp


【解决方案1】:

在您的 sendData 方法中,您将对象序列化为内存流,然后将其读回 2048 字节的缓冲区,然后再将其写入网络流。如果序列化的对象 > 2048 字节,您将遇到问题。我会尝试直接序列化到网络流,或者至少使用与 ReadData 方法中相同类型的代码,在该方法中逐字节写入。

编辑:

数据的大小可能不是问题。您仍然应该避免硬编码缓冲区大小并坚持您在评论中提到的代码更改。鉴于您的评论,问题出在其他地方。 在您的发送者和接收者中,您写入一个内存流,然后从中读取。除非您在写入和读取之间将流中的当前位置设置回零,否则您不能这样做。

所以在客户端的 sendData 方法中添加一行

mstream.Seek(0, SeekOrigin.Begin);

紧接着

bform.Serialize(mstream, data);

然后在服务器的 ReadData 方法中添加该行

memStream.Seek(0, SeekOrigin.Begin);

就在之前

Packet packet = (Packet)bform.Deserialize(memStream);

这样,在您尝试读取之前,内存流被设置为开头。

我认为你可以一起跳过内存流,只读取和写入网络流,但你可能有其他原因。

【讨论】:

  • 我试过这段代码:while ((bytes = mstream.ReadByte()) != -1) { stream.WriteByte((byte)bytes);流。冲洗(); } 但它引发了另一个异常 :( 类似于“尝试重建空流”。
猜你喜欢
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-01
相关资源
最近更新 更多