C# 反序列化通过TCP发送的数据
我无法通过TCPClient发送对象。首先,我将它们序列化为字节数组,然后发送它们。TCPListener接收到一些数据,但反序列化程序正在引发异常“意外的流结束” 以下是接收器代码:C# 反序列化通过TCP发送的数据,c#,.net,serialization,tcp,C#,.net,Serialization,Tcp,我无法通过TCPClient发送对象。首先,我将它们序列化为字节数组,然后发送它们。TCPListener接收到一些数据,但反序列化程序正在引发异常“意外的流结束” 以下是接收器代码: public void start() { TcpListener listener = new TcpListener(IPAddress.Any, 8090); listener.Start(); while (true) {
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();
}
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);
}
接收器主要方法:
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();
}
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);
}
在sendData方法中,将对象序列化为内存流,然后在将其写入网络流之前将其读回2048字节的缓冲区。如果序列化对象大于2048字节,则会出现问题。我会尝试直接序列化到网络流,或者至少使用与ReadData方法相同的代码,在ReadData方法中逐字节写入 编辑: 数据的大小可能不是问题所在。您仍然应该避免硬编码的缓冲区大小,并坚持您在注释中提到的代码更改。根据你的评论,问题在别处。 在发送方和接收方中,您都向内存流写入数据,然后从中读取数据。除非在写入和读取之间将流中的当前位置设置回零,否则无法执行此操作 因此,在客户端的sendData方法中添加以下行
mstream.Seek(0, SeekOrigin.Begin);
memStream.Seek(0, SeekOrigin.Begin);
紧接着
bform.Serialize(mstream, data);
在服务器的ReadData方法中添加以下行
mstream.Seek(0, SeekOrigin.Begin);
memStream.Seek(0, SeekOrigin.Begin);
就在之前
Packet packet = (Packet)bform.Deserialize(memStream);
这样,在您尝试读取内存流之前,内存流就被设置为开始
我认为您可以跳过所有内存流,只读取和写入网络流,但可能还有其他原因。我尝试了以下代码:while((bytes=mstream.ReadByte())!=-1){stream.WriteByte((byte)bytes);stream.Flush()}但它抛出了另一个例外:(类似于“尝试重建空流”。你有解决过这个问题吗?