2009-09-30 67 views
3

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

这里是reciever代码:

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

Reciever主要方法:

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); 
    } 
+0

你有没有把这个问题整理出来? – 2009-10-13 08:27:23

回答

3

在您的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); 

这样,在尝试从中读取内存流之前,将内存流设置为开始。

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

+0

我试过这个代码: while((bytes = mstream.ReadByte())!= -1) { stream.WriteByte((byte)bytes); stream.Flush(); } 但它引发了另一个异常:(类似“尝试重建空流”。 – Klinki 2009-09-30 20:17:32

相关问题