2009-09-30 66 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

相關問題