从封闭的NetworkStream读取不会引起任何异常 [英] Reading from closed NetworkStream doesn't cause any exception

查看:168
本文介绍了从封闭的NetworkStream读取不会引起任何异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个相当简单的客户端 - 服务器应用程序,但对于通信我想使用二进制序列化对象。通信本身看起来相当不错,但是当我关闭客户端的侧流,服务器并没有真正注意到它,并不断尝试读取数据流。

I'm trying to create a rather simple client-server application, but for communication I want to use binary serialized objects. The communication itself seems rather fine, but when I close the stream on the client's side, the server doesn't really notice it and keeps on trying to read the stream.

服务器端(Server类,在不同的线程中执行):

server side (class Server, executed in separate thread):

监听连接

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");
}



添加客户端:

adding the client:

    public void AddClient(TcpClient socket)
    {
        Client client = new Client(this, socket);
        this.clients.Add(client);
        client.Start();
    }



听消息(深客户端类中):

listening for messages (deep inside Client class):

BinaryFormatter deserializer = new BinaryFormatter();
while (!interrupted)
{
    System.Diagnostics.Debug.WriteLine("Waiting for the message...");
    AbstractMessage msg = (AbstractMessage)deserializer.Deserialize(stream);
    System.Diagnostics.Debug.WriteLine("Message arrived: " + msg.GetType());
    raiseEvent(msg);
}



单元测试:

unit test:

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();



因此,该消息得到正确读取,但后来,当我关闭流,deserializer.Deserialize(流)似乎不抛出任何异常...所以应该只是无法读取这种方式,或者我应该关闭客户端以不同的方式?

so the message gets read properly, but then, when I close the stream, deserializer.Deserialize(stream) doesn't appear to throw any exceptions... so should it just not be read this way, or should I close the client in a different way?

推荐答案

假设服务器中使用的反序列化的信息流是的的NetworkStream (这是由 TcpClient.GetStream()的返回流的类型),你应该做两件事情:

Assuming the stream used in the Server for deserializing the message is a NetworkStream (which is the type of the stream returned by TcpClient.GetStream()), you should do two things:


  1. 定义连接两端的具体消息。当服务器接收和反序列化此消息,退出while循环。为了使这项工作,客户显然需要关闭其TcpClient的连接之前发送这样的消息。 (您可以选择不同的机制以类似的方式工作 - 但为什么不使用消息机制,你已经在地方...)

  1. Define a specific message for "connection ends". When the server receives and deserializes this message, exit the while-loop. To make this work, the client obviously needs to send such a message before closing its TcpClient connection. (You might choose a different mechanism working in a similar manner -- but why not using the message mechanism you already have in place...)

设置 ReadTimeout 上的的NetworkStream 的,所以在情况下,连接丢失,客户不能发送一个连接终止的消息时,服务器将达到超时,实现了客户端是死

Set a ReadTimeout on the NetworkStream, so in case the connection gets lost and the client is unable to send a "connection ends" message, the server will hit the timeout and realize that the client is "dead".

在你的服务器的代码,用于收听的客户端消息应类似于这样:

The code in your server for listening to client messages should look similar to this:

//
// 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...
}

这篇关于从封闭的NetworkStream读取不会引起任何异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆