我实现了一个使用Socket和线程
的客户端和服务器模型当我想只从客户端传递一个字符串到服务器时,它可以工作。但我想传递一个对象,它会抛出这个错误: “试图反序列化空流”
以下是代码:
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以反序列化。这是对的吗?
谢谢
答案 0 :(得分:2)
您永远不会使用从流中读取的消息。您正在读取的内存流是空的。
另外,为什么要使用这些中间MemoryStream?
答案 1 :(得分:2)
我也推荐WCF。但是,如果继续使用套接字,协议中缺少的关键元素是message framing。
答案 2 :(得分:1)
回答第二个问题:为了获得最大的可维护性,类Command
应位于客户端和服务器引用的单独程序集中。
要回答您的第一个问题:您正尝试从服务器上的空流反序列化,就像例外情况告诉您的那样。在从clientStream
反序列化之前,您需要将从memoryStream
读取的字节复制到memoryStream
。或者,直接使用clientStream
而不是memoryStream
;这可能需要重新考虑您的协议。
最后,我全心全意地同意@Andrey:考虑使用WCF。它比原始套接字更好。
答案 3 :(得分:0)
如果更改服务器代码以使用其他MemoryStream构造函数,问题就会消失。
MemoryStream memoryStream = new MemoryStream(message, 0, bytesRead);
但是,我同意斯蒂芬和其他人的意见。使用WCF,或使用消息框架。
答案 4 :(得分:0)
另一个问题:我从客户端复制了类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或消息框架可能更容易,但我通常没有机会坐下来读书。
答案 5 :(得分:0)
不应将bytesRead传递给实际上是字节流长度的MemoryStream,而应传递'message',因为它是实际的字节流。像,
MemoryStream memoryStream = new MemoryStream(message);
当您传递整数变量时,编译器会抛出流为空的异常。
至于WCF,它是非凡的框架,但对于需要低延迟和高性能的应用程序,WCF是一个可怕的答案,因为它的开销,它建立在套接字上。因此,如果您使用套接字,那将是最低级别的实现,因此,最快。这取决于你的应用程序你应该选择的范例......