Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过TCP发送大型对象:“;解析完成前遇到的流结束";_C#_Serialization_Tcp_Tcpclient - Fatal编程技术网

C# 通过TCP发送大型对象:“;解析完成前遇到的流结束";

C# 通过TCP发送大型对象:“;解析完成前遇到的流结束";,c#,serialization,tcp,tcpclient,C#,Serialization,Tcp,Tcpclient,每当我试图从网络流中反序列化双工列表时,我总是收到一个序列化异常: 之前遇到的流结束 解析已完成 我有一个简单的客户机-服务器体系结构:我的TcpTransportClient包装了TcpClient的功能,我使用了两种基本方法:Send(发送消息)和Receive(直到收到消息为止) 发送函数接收一条消息,使用二进制格式化程序对其进行序列化,并通过网络流发送字节 public void Send(Message message) { if (message == null) {

每当我试图从
网络流中反序列化双工列表时,我总是收到一个
序列化异常

之前遇到的流结束 解析已完成

我有一个简单的客户机-服务器体系结构:我的
TcpTransportClient
包装了
TcpClient
的功能,我使用了两种基本方法:
Send
(发送消息)和
Receive
(直到收到消息为止)

发送
函数接收一条
消息
,使用
二进制格式化程序
对其进行序列化,并通过
网络流
发送字节

public void Send(Message message)
{
    if (message == null)
    {
        throw new TransportException("Invalidate Parameter In Send Call");
    }

    if (_tcpClient == null || !_tcpClient.Connected)
    {
        throw new TransportException("Client Not Connected");
    }

    lock (_sync)
    {
        // Serialzie the message
        MemoryStream memStream = new MemoryStream();
        _serializer.Serialize(memStream, message);

        // Get the bytes of of the memory stream
        byte[] buffer = memStream.GetBuffer();

        // Write the message to the network stream
        NetworkStream networkStream = _tcpClient.GetStream();
        networkStream.Write(buffer, 0, buffer.Length);
        networkStream.Flush();
    }
}
接收函数从
网络流
将字节读入缓冲区,然后使用
二进制格式化程序对消息进行反序列化:

public Message Receive()
{
    if (_tcpClient == null || !_tcpClient.Connected)
    {
        throw new TransportException("Client Not Connected");
    }

    byte[] buffer;
    MemoryStream memStream = new MemoryStream();
    NetworkStream netStream = _tcpClient.GetStream();
    try
    {
        do
        {
            // Allocate a new buffer
            buffer = new byte[_tcpClient.ReceiveBufferSize];

            // Read the message buffer
            int sizeRead = netStream.Read(buffer, 0, buffer.Length);

            // Write the buffer to the memory stream
            memStream.Write(buffer, 0, sizeRead);

        } while (netStream.DataAvailable);

        // Reset the memory stream position
        memStream.Position = 0;

        // Deserialize the message
        object tmp = _deserializer.Deserialize(memStream); // <-- The exception is here!

        // Cast the object to a message
        return (Message)tmp;
    }
    catch (System.Exception e)
    {
        if (_tcpClient == null || !_tcpClient.Connected)
        {
            throw new TransportException("Client Not Connected");
        }
        else
        {
            throw e;
        }
    }
}
当我尝试在我的
TcpTransportClient
Receive
方法中对消息进行反序列化时,总会出现异常,但只有在数据集中放入一些数据时才会出现问题。通过网络发送值列表并在接收端成功反序列化它们的正确方法是什么

顺便说一句,我尝试了一个解决方案,但没有成功:我仍然得到同样的异常

while(netStream.DataAvailable)


那是不对的。当Read()调用返回0时,应该停止读取。DataAvailable属性只是告诉您Read()调用是否会阻塞,等待服务器赶上。

您需要。

好吧,Read blocks,所以我从未让它返回0。它永远不会脱离while循环。如果保持连接打开,则必须首先发送列表的长度。接收器可以读取此长度,然后将确切知道要读取多少字节()。
TcpTransportClient client = new TcpTransportClient(GetLocalAddress(), servicePort);
client.Connect();

Thread sendThread = new Thread(() =>
{
    List<double> dataSet = new List<double>();
    for (double d = 0.0; d < 500.0; d++)
    {
        dataSet.Add(d);
    }

    while (true)
    {
        try
        {
            // Serialize the data set
            MemoryStream memStream = new MemoryStream();
            BinaryFormatter binFormat = new BinaryFormatter();
            binFormat.Serialize(memStream, (object)dataSet);

            // Create a message
            Message msg = new Message();

            // Hold the object bytes in an opaque field
            msg.SetFieldValue(1000, memStream.GetBuffer());

            // Set the message topic
            msg.SetTopic("client.dataSet");

            // Send the message
            client.Send(msg);

            // Sleep
            Thread.Sleep(3000);
        }
        catch (TransportException)
        {
            break;
        }
        catch(Exception)
        {
            //ignore it
        }
    }
});
sendThread.IsBackground = true;
sendThread.Start();
public void HandleAcceptedClient(TcpTransportClient client)
{
    Thread receiveThread = new Thread(() =>
    {
        while (true)
        {
            try
            {
                Message msg = client.Receive();
                Trace.WriteLine("Server Received: " + msg.GetTopic());
                byte[] buffer = msg.GetFieldOpaqueValue(1000);
                MemoryStream memStream = new MemoryStream(buffer);
                BinaryFormatter binFormat = new BinaryFormatter();

                List<double> dataSet = (List<double>)binFormat.Deserialize(memStream);
                if (dataSet.Count == 500)
                {
                    Trace.WriteLine(DateTime.Now + ": OK");
                }
                else
                {
                    Trace.WriteLine(DateTime.Now + ": FAIL");
                }
            }
            catch (TransportException)
            {
                break;
            }
            catch(Exception)
            {
                // ignore it
            }

        }

    });
    receiveThread.IsBackground = true;
    receiveThread.Start();
}