簡體   English   中英

套接字和序列化C#問題

[英]Problem with Socket and Serialization C#

我實現了將套接字與線程一起使用的客戶端和服務器模型

當我只希望將字符串從客戶端傳遞到服務器時,它可以工作。 但是我想傳遞一個對象,它將引發此錯誤:“試圖反序列化空流”

這是代碼:


客戶:

ASCIIEncoding asen = new ASCIIEncoding();

MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
Command command = new Command("meuLogin", "minhaSenha");
binaryFormatter.Serialize(memoryStream, command);

stream.Write(memoryStream.ToArray(), 0, memoryStream.ToArray().Length);

服務器:

byte[] message = new byte[4096];
int bytesRead = 0;
bytesRead = clientStream.Read(message, 0, 4096);

MemoryStream memoryStream = new MemoryStream(bytesRead);
BinaryFormatter bf1 = new BinaryFormatter();
memoryStream.Position = 0;

Command command = (Command)bf1.Deserialize(memoryStream); 

另一個問題:我從客戶端復制了Command類,並粘貼到Server上進行反序列化。 這個對嗎?

謝謝

您永遠不會使用從流中讀取的消息。 您正在讀取的內存流因此為空。

附帶說明一下,為什么要使用這些中間MemoryStream?

我還建議使用WCF。 但是,如果繼續使用套接字,則協議中缺少的關鍵元素是消息框架

回答您的第二個問題:為了獲得最大的可維護性, Command類應該在客戶端和服務器都引用的單獨程序集中。

回答您的第一個問題:您正嘗試從服務器上的空流中反序列化,就像異常告訴您的那樣。 在從clientStream反序列memoryStream之前,需要將從clientStream讀取的字節復制到memoryStream 或者,直接使用clientStream而不是使用memoryStream 這可能需要重新考慮您的協議。

最后,我完全同意@Andrey:考慮使用WCF。 它比原始套接字更好。

而不是將bytesRead傳遞給實際上是字節流長度的MemoryStream,而應該傳遞“ message”,因為它是實際的字節流。 喜歡,

MemoryStream memoryStream = new MemoryStream(message);

當您傳遞整數變量時,編譯器將拋出異常,即流為空。

對於WCF,這是一個了不起的框架,但是對於要求低延遲和高性能的應用程序,WCF是基於套接字的,因為它的開銷是一個可怕的答案。 因此,如果使用套接字,那將是最低級別的實現,因此也是最快的實現。 這取決於您的應用程序應該選擇哪種范式...

如果將服務器代碼更改為使用其他MemoryStream構造函數,則問題將消失。

MemoryStream memoryStream = new MemoryStream(message, 0, bytesRead);

但是,我同意斯蒂芬和其他人的看法。 使用WCF或使用消息框架。

另一個問題:我從客戶端復制了Command類,並粘貼到Server上進行反序列化。 這個對嗎?

否。您的客戶端和服務器的名稱空間可能不同,因此服務器將嘗試反序列化與其名稱空間匹配的流。

您應該使用自己的命名空間創建命令類,並從客戶端和服務器兩者中引用它。

之后...

客戶:

static void StreamToServer(TcpClient client, Command obj) {
  using (NetworkStream ns = client.GetStream()) {
    using (MemoryStream ms = new MemoryStream()) {
      BinaryFormatter formatter = new BinaryFormatter();
      formatter.Serialize(ms, obj);
      byte[] buf = ms.ToArray();
      ns.Write(buf, 0, buf.Length);
    }
  }
}

服務器:

static Command ReadStream(TcpListener listener) {
  Command obj = null;
  using (TcpClient client = listener.AcceptTcpClient()) { // waits for data
    using (NetworkStream ns = client.GetStream()) {
      byte[] buf = new byte[client.ReceiveBufferSize];
      int len = ns.Read(buf, 0, buf.Length);
      using (MemoryStream ms = new MemoryStream(buf, 0, len)) {
        BinaryFormatter formatter = new BinaryFormatter();
        obj = formatter.Deserialize(ms) as Command;
      }
    }
  }
  return obj;
}

WCF或消息框架可能更容易,但是我經常沒有機會在工作中坐下來閱讀一本書。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM