C# 从封闭的网络流读取数据不会';不要引起任何例外
我试图创建一个相当简单的客户机-服务器应用程序,但对于通信,我希望使用二进制序列化对象。通信本身似乎很好,但当我关闭客户端的流时,服务器并没有真正注意到它,而是继续尝试读取流 服务器端(类服务器,在单独的线程中执行): 监听连接C# 从封闭的网络流读取数据不会';不要引起任何例外,c#,C#,我试图创建一个相当简单的客户机-服务器应用程序,但对于通信,我希望使用二进制序列化对象。通信本身似乎很好,但当我关闭客户端的流时,服务器并没有真正注意到它,而是继续尝试读取流 服务器端(类服务器,在单独的线程中执行): 监听连接 listener = new TcpListener(IPAddress.Parse("127.0.0.1"), this.Port); listener.Start(); while (!interrupted) { Console.WriteLine("Wa
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), this.Port);
listener.Start();
while (!interrupted)
{
Console.WriteLine("Waiting for client");
TcpClient client = listener.AcceptTcpClient();
AddClient(client);
Console.WriteLine("Client connected");
}
添加客户端:
public void AddClient(TcpClient socket)
{
Client client = new Client(this, socket);
this.clients.Add(client);
client.Start();
}
侦听消息(深入客户端类):
单元测试:
Server server = new Server(6666);
server.Start();
Thread.Sleep(500);
TcpClient client = new TcpClient("127.0.0.1", 6666);
var message = new IntroductionMessage();
byte[] arr = message.Serialize();
client.GetStream().Write(arr, 0, arr.Length);
Thread.Sleep(500);
Assert.AreEqual(1, server.Clients.Count);
client.GetStream().Close();
client.Close();
Thread.Sleep(1000);
Assert.AreEqual(0, server.Clients.Count);
server.Stop();
因此消息被正确读取,但是,当我关闭流时,反序列化器。反序列化(流)似乎不会引发任何异常。。。那么,是不是不应该以这种方式读取,还是应该以其他方式关闭客户端?假设服务器中用于反序列化消息的流是a(这是TcpClient.GetStream()返回的流的类型),您应该做两件事:
//
// Time-out after 1 minute after receiving last message
//
stream.ReadTimeOut = 60 * 1000;
BinaryFormatter deserializer = new BinaryFormatter();
try
{
while (!interrupted)
{
System.Diagnostics.Debug.WriteLine("Waiting for the message...");
AbstractMessage msg = (AbstractMessage)deserializer.Deserialize(stream);
System.Diagnostics.Debug.WriteLine("Message arrived: " + msg.GetType());
//
// Exit while-loop when receiving a "Connection ends" message.
// Adapt this if condition to whatever is appropriate for
// your AbstractMessage type.
//
if (msg == ConnectionEndsMessage) break;
raiseEvent(msg);
}
}
catch (IOException ex)
{
... handle timeout and other IOExceptions here...
}
服务器从哪里获取流?服务器对象中的TcpListener实例?现在,我更新了question@Kamil:根据消息的原始大小和使用软件的(网络)环境,您必须选择一个相当大的超时时间(以适应糟糕的酒店互联网连接,甚至可能是糟糕的调制解调器连接,嗯…)。在我的示例中,我选择了一分钟超时。如果您的程序仅在LAN中运行(或在低延迟internet连接上运行),则您可以选择小于30秒的超时。在任何情况下,都不要仅依赖超时,并实现专用的“连接结束”消息。这将极大地帮助您排除问题,因为您不清楚问题是客户端还是服务器中的错误,还是internet/网络连接的问题。。。
//
// Time-out after 1 minute after receiving last message
//
stream.ReadTimeOut = 60 * 1000;
BinaryFormatter deserializer = new BinaryFormatter();
try
{
while (!interrupted)
{
System.Diagnostics.Debug.WriteLine("Waiting for the message...");
AbstractMessage msg = (AbstractMessage)deserializer.Deserialize(stream);
System.Diagnostics.Debug.WriteLine("Message arrived: " + msg.GetType());
//
// Exit while-loop when receiving a "Connection ends" message.
// Adapt this if condition to whatever is appropriate for
// your AbstractMessage type.
//
if (msg == ConnectionEndsMessage) break;
raiseEvent(msg);
}
}
catch (IOException ex)
{
... handle timeout and other IOExceptions here...
}