Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何处理.NET中的套接字断开连接?_C#_.net_Sockets - Fatal编程技术网

C# 如何处理.NET中的套接字断开连接?

C# 如何处理.NET中的套接字断开连接?,c#,.net,sockets,C#,.net,Sockets,我正在构建一个(LAN)网络应用程序,因此由于各种可能的原因,连接总是有可能断开。我正试图想出一个好的设计来处理这个问题,这样它就不会影响应用程序的其余部分。我写了一个快速的东西来尝试这样做,但我认为它可以提高很多。我感谢您的帮助和经验,了解处理此问题的最佳方法 这是我的第一次尝试: class ConnectionWrapper { NetworkStream stream; StreamReader reader; Endpoint endPoint; boo

我正在构建一个(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;
        }
    }
}
不是很优雅,也可能不是最好的。你能分享一下你的经验吗,甚至可以建议一个现有的图书馆


谢谢。

老实说,我认为您不应该让连接包装器包含处理自己的连接策略的逻辑。我认为这应该在这个类之外完成,特别是不要在catch语句中。使用某种ConnectionController对象来处理连接失败后是否应重试连接。

我本来打算编辑我的文章,但这应该与我上一篇文章完全分开

在我看来,您的逻辑是完全错误的,您应该在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代码放在一个线程中,这样就不会阻塞应用程序的其余部分。通过通知观察者更改,他们可以通过执行类似myConnectionWrapper.getMessages()的操作来获取ArrayList;它将返回ArrayList,但同时也会清除ArrayList,如下所示:

public ArrayList getMessages() {
     ArrayList temp = arr;
     arr.clear();
     return temp;
}
这样,您可以获取所有消息并将它们从队列中清除

我以前写过网络客户端,这是其中一个的总体设计。您将有两个线程不断旋转,一个线程发送到接收方消息,另一个线程发送消息


应该使用某种管理器代码来处理逻辑,以确定是继续,还是重新连接,或者执行任何您想执行的操作。

谢谢。我同意这个地方不应该成为限制条件,但正是因为我缺乏经验才这样做的如果你能抽出时间举个例子,我会很感激的。谢谢你@Kezzer。实际上,我的包装器类的使用方式与您描述的类似。一个线程使用它读取消息并将它们添加到队列中,另一个线程使用该队列处理输入。但是,我想将所有连接逻辑封装在连接包装器类中。。。。。。套接字(不是流)的
Connected
属性对于此特定问题没有用处。根据MSDN中的文档,它返回上次I/O操作时的连接状态。同一页显示了如何通过发送零字节数组来了解套接字是否已连接。。。。。。最后,“getMessages()”方法将清除返回的数组,因为temp和arr引用同一个对象。可能您的意思是“temp=arr.Clone()”或类似的内容。这取决于您决定如何处理入站消息队列。在我的实现中,我将队列交给主控制器,因此在检索到队列后清除队列实际上是一个逻辑步骤。否则,您如何区分哪些是新的,哪些不是?要区分哪些是新的,哪些不是,我对队列使用
volatile
计数,对已使用的消息使用(线程本地)计数。