我该如何处理.NET中的套接字断开连接?

时间:2009-02-04 14:12:07

标签: c# .net sockets

我正在构建一个(LAN)网络应用程序,因此出于各种可能的原因,总是有可能断开连接。我试图想出一个处理这个问题的好设计,这样它不会影响应用程序的其余部分。我写了一个快速的尝试去做,但我认为它可以增强很多。感谢您对处理此问题的最佳方式的帮助和经验。

这是我的第一次试验:

class ConnectionWrapper {
    NetworkStream stream;
    StreamReader reader;
    Endpoint endPoint;
    bool endOfStream;
    int maxRetries = 5;

    public void connect() {
        // ... code to initialize a (TCP) socket to endPoint
        this.stream = new NetworkStream(socket, true);
        this.reader = new StreamReader(stream);
    }

    string readNextMsg() {
        try {
            string msg = reader.ReadLine();
            if (msg == "EOF") endOfStream = true;
            return msg;
        }
        catch (IOException e) {
            Exception ex = e;
            while (maxRetries-- > 0) {
                try { connect(); ex = null; }
                catch (Exception e2) { ex = e2; }
            }
            if (x != null) throw ex;
        }
    }
}

不是很优雅,可能不是最好的。您能否分享一下您的经验,甚至可以建议现有的图书馆?

谢谢。

2 个答案:

答案 0 :(得分:2)

老实说,我认为您不应该让连接包装器包含处理自己的连接策略的逻辑。我认为这应该从这个类的外部完成,特别是在catch语句中。有一些ConnectionController对象来处理一旦失败就应该重试连接。

答案 1 :(得分:2)

我打算编辑我​​的帖子,但这应该与我的上一篇完全分开。

在我看来,你的逻辑是完全错误的,你应该在ConnectionWrapper中有一个线程,它在StreamReader上旋转拉出消息并将它们放在队列中。然后,此队列通知侦听器更改。然后,听众会自己检索数据并决定需要对它们进行哪些操作。

class ConnectionWrapper {
    NetworkStream stream;
    StreamReader reader;
    Endpoint endPoint;
    bool endOfStream;
    int maxRetries = 5;
    ArrayList arr;

    public void connect() {
        // ... code to initialize a (TCP) socket to endPoint
        this.stream = new NetworkStream(socket, true);
        this.reader = new StreamReader(stream);
    }

    private void initReceiverThread() {
        String line;

        while(stream.isConnected() && (line = reader.readLine()) != null) {
           // notify observers of a change
           arr.add(line);
        }
    }
}

这是伪代码我警告你,我从未在C#中这样做过。一个典型的读者实际上在readLine语句上等待,因此while循环不会发疯。最好将initReceiverThread代码放在Thread中,这样它就不会阻塞应用程序的其余部分。通过向观察者通知更改,他们可以通过执行类似myConnectionWrapper.getMessages()的操作来获取ArrayList;它将返回一个ArrayList,同时也清除ArrayList,如下所示:

public ArrayList getMessages() {
     ArrayList temp = arr;
     arr.clear();
     return temp;
}

通过这种方式,您可以获取所有消息并将其从队列中清除。

我以前写过网络客户端,这是一个通用设计。你将有两个线程不断旋转,一个接收消息,一个发送它们。

逻辑应该用某种管理器代码来处理,以确定是继续,还是重新连接或者你想做什么。