C # Всегда повторять TCP-соединение, если соединение не удалось - PullRequest
0 голосов
/ 17 сентября 2018

ниже - мой код для запуска tcp-подключения моих клиентов к серверу:

Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);

ConnectCallback:

    private void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.  
            Socket client = (Socket)ar.AsyncState;

            // Complete the connection.  
            client.EndConnect(ar);
        }
        catch (Exception ex)
        {
            _logger.Info(ex.ToString());
        }
    }

Но мой код устанавливает соединение только один раз, когда моя система запускается.Как нам повторить попытку подключения, если первая попытка не удалась

И всегда будет повторять попытку, если соединение всегда прерывается?

А может быть, повторять попытку каждые 30 секунд?

1 Ответ

0 голосов
/ 17 сентября 2018
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);

Если вы хотите отслеживать неудачные попытки и хотите сохранить хороший старый асинхронный шаблон, я бы передал объект состояния:

class ConnectionState {
    Socket Client {get; set;}
    int FailedAttempts {get; set;} = 0;
}

Тогда передайте это:

client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), new ConnectionState(){ .Client = client, FailedAttempts = 0});

В обратном вызове:

private void ConnectCallback(IAsyncResult ar)
{
    ConnectionState state = (ConnectionState)ar.AsyncState;
    try
    {
        state.Client.EndConnect(ar);
    }
    catch (SocketException ex)
    {
        _logger.Info(ex.ToString());
        if( state.FailedAttempts < MAX_ATTEMPTS )
        {
            state.FailedAttempts += 1;
            state.Client.BeginConnect( remoteEP, new AsyncCallback(ConnectCallback), state );

            // you may also check the exception for what happened exactly.
            // There may be conditions where retrying does not make sense.
            // See SocketException.ErrorCode
        }
        else
        {
            // You may want to handle exceeding max tries.
            // - Notify User
            // - Maybe throw a custom exception
        }
    }
}

Ссылка на коды ошибок SocketException: https://docs.microsoft.com/en-us/windows/desktop/winsock/windows-sockets-error-codes-2

Для настройки механизма повтора, основанного на времени, я бы создал своего рода «сторожевой таймер соединения»: каждые 10 секунд проверяйте поле клиента по таймеру. Если оно пустое, а попытка подключения еще не запущена, запустите ее.


Лично я бы попробовал переключиться на TPL . Но я считаю это альтернативой, а не прямым ответом на ваш вопрос. Но я рекомендую это.

...