我遇到通过TCPClient发送对象的问题。首先,我将它们序列化为字节数组然后发送它们。 TCPListener收到一些数据,但反序列化器抛出异常“意外的流结束”。
以下是收件人代码:
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);
}
答案 0 :(得分: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);
这样,在您尝试读取内存流之前,内存流就会设置为开头。
我认为您可以一起跳过内存流,只读取和写入网络流,但您可能还有其他原因。