我是C#的新手,我想知道,使用tcpClient发送对象的最简单方法是什么,迭代了以下代码,但抛出了一个错误的错误客户端代码:
TcpClient client = new TcpClient(ip, port);
StreamWriter writer = new StreamWriter(client.GetStream());
NetworkStream strm = client.GetStream();
BinaryFormatter formatter = new BinaryFormatter();
Transaction tx = new transaction();
string msg = string.Empty;
msg = "transaction";
writer.WriteLine(msg);
writer.Flush();
formatter.Serialize(strm,tx);
在接收端
服务器代码:
while(true){
TcpClient client = server.AcceptTcpClient();
IFormatter formatter = new BinaryFormatter();
NetworkStream strm = client.GetStream();
StreamReader reader = new StreamReader(client.GetStream());
string msg = string.Empty;
while (!((msg = reader.ReadLine()).Equals("exit"))){
Transaction tx = (Transaction)formatter.Deserialize(strm);
}
它在服务器上产生此错误
input stream is not a valid ibinary format intital content is :0c-02-00-00 .....
所以有人可以帮我吗,或者还有其他使用tcpclient发送对象的简单干净的方法吗?
这里的潜在问题与混合两种不同的机制以读写流有关的方式有关,特别是:使用StreamReader
和基于流的单独解析器。使用这样做也是一个坏主意StreamWriter
,但是...我想您一定会避免的,尽管它仍然是一个坏主意。
这里的问题StreamReader
是贪婪。当您要求它发送一行时,它不会从流中逐字节读取以寻找\r
or \n
,而是从流中获取数据缓冲区,然后按要求对其进行处理。这样,它假定它现在是流的唯一所有者。
所以; 当您这样做时:
while (!((msg = reader.ReadLine()).Equals("exit"))){
Transaction tx = (Transaction)formatter.Deserialize(strm);
}
读取器消耗的不仅是"transaction\r\n
“-它消耗了这一行和后面的内容,还有一些未定义的字节数。”然后,当BinaryFormatter
尝试读取流时,它发现自己在消息中途出现,并在火花中爆炸。
理想情况下,将自己限制为一种序列化机制。含义:输StreamReader
/StreamWriter
完全在这里。
如果我可以提出一个使用protobuf-net和继承的替代机制:
[ProtoContract]
[ProtoInclude(1, typeof(ShutdownMessage))]
[ProtoInclude(2, typeof(TransactionMessage))]
public abstract class MessageBase {}
[ProtoContract]
public sealed class ShutdownMessage : MessageBase {}
[ProtoContract]
public sealed class TransactionMessage : MessageBase {
// your data here
}
现在,您可以通过以下方式发送任意数量的邮件:
public void Send(MessageBase message) {
Serializer.SerializeWithLengthPrefix(strm, message, PrefixStyle.Base128);
}
并通过以下方式接收任意数量的消息:
while (true) {
var msg = Serializer.DeserializeWithLengthPrefix<MessageBase>(strm, PrefixStyle.Base128);
if (msg is null || msg is ShutdownMessage) break; // all done
switch (msg)
{
case TransactionMessage tx: ProcessTransaction(tx); break;
// etc
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句