Как я должен обрабатывать разъединения сокетов в .NET? - PullRequest
2 голосов
/ 04 февраля 2009

Я создаю сетевое приложение (ЛВС), поэтому всегда есть вероятность, что соединение будет разорвано по разным причинам. Я пытаюсь придумать хороший дизайн для решения этой проблемы, чтобы он не влиял на остальную часть приложения. Я написал небольшую вещь, чтобы попытаться сделать это, но я думаю, что это может быть значительно улучшено. Я ценю вашу помощь и опыт о том, как решить эту проблему.

Это мое первое испытание:

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 ]

2 голосов
/ 04 февраля 2009

Я собирался редактировать свое сообщение, но оно должно быть полностью отделено от моего последнего.

На мой взгляд, ваша логика неверна, в 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 в поток, чтобы он не блокировал остальную часть приложения. Уведомив наблюдателей об изменениях, они могут затем пойти и получить ArrayList, выполнив что-то вроде myConnectionWrapper.getMessages (); который будет возвращать ArrayList, но одновременно очищать ArrayList, например, так:

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

Таким образом, вы получаете ВСЕ сообщения и удаляете их из очереди.

Я раньше писал сетевых клиентов, и это общий дизайн одного из них. У вас будет два потока, которые постоянно вращаются: один для получения сообщений и один для их отправки.

Логика должна быть связана с каким-то кодом менеджера, чтобы определить, продолжить ли, или переподключиться, или что вы хотите сделать.

2 голосов
/ 04 февраля 2009

Честно говоря, я не думаю, что вы должны позволять оболочке соединений содержать логику для обработки собственной политики соединений. Я думаю, что это должно быть сделано за пределами этого класса, и особенно не в выражении catch. Имейте некоторый объект ConnectionController, чтобы иметь дело с тем, следует ли повторять попытку подключения после сбоя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...