Повторно открыть подключенный сокет датаграммы - PullRequest
1 голос
/ 22 сентября 2010

У меня есть протокол подключения, который был определен нашим клиентом. Данные передаются между двумя компьютерами Linux с использованием протоколов UDP и TCP. IP-адреса и порты фиксируются при запуске.

Мы отправляем сообщения с частотой 200 Гц, и я использую соединение, чтобы сэкономить время на передачах.

Моя проблема в том, что в случае ошибки связи мне нужно разорвать соединения и повторно инициализировать.

У меня проблема с одним из соединений UDP, так как он не будет повторно привязан к нужному адресу и возвращает errno 22.

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

int  
doConnect(int& sock, int local_port, char *local_ip, int remote_port, char *remote_ip)  
{  
    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);  
    struct sockaddr_in addr;  

    memset(&addr, 0, sizeof(sockaddr_in);  
    addr.sin_family = AF_INET;  
    addr.sin_port = htons(local_port);  
    inet_pton(local_ip,&addr.sin_addr.s_addr); 

    if (0 > bind(sock, (struct sockaddr*)&addr, sizeof(addr)))  
    {
        printf("Bind Error errno = %d\n", errno);
        return ERR_BIND;  
    }

    memset(&addr, 0, sizeof(sockaddr_in);  
    addr.sin_family = AF_INET;  
    addr.sin_port = htons(remote_port);  
    inet_pton(remote_ip,&addr.sin_addr.s_addr); 

    if (0 > connect(sock, (struct sockaddr*)&addr, sizeof(addr)))  
    {
        printf("Connect Error errno = %d\n", errno);
        return ERR_CONNECT;  
    }
    return ERR_OK;
}

Способ, которым это используется, выглядит следующим образом:

int s1(-1), s2(-1);  
doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");  
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");  

При возникновении ошибки

close(s1);
close(s2);

doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");

Здесь локальный адрес 172.17.21.3, и я подключаюсь к 172.17.21.1. s1 прослушивает широковещательное сообщение.

s1 успешно переподключается к удаленному компьютеру, но s2 завершается ошибкой с ошибкой 22 от вызова для привязки.

Я попытался явно вызвать bind и подключиться к адресу AF_UNSPEC непосредственно перед тем, как закрыть сокет. Это не решает проблему.

Есть ли варианты, которые я должен использовать?

Ответы [ 2 ]

2 голосов
/ 22 сентября 2010

Возможно, вы могли бы попробовать:

 int val = 1;
 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));

Я также рекомендую вам дважды проверить, что вы не передаете одинаковый сокет двум последовательным вызовам doConnect () (например, errno 22 = EINVAL, что в случае bind () означает, что сокет уже привязан к адресу).

0 голосов
/ 22 сентября 2010

Нижележащий уровень сокета может держать порт и IP-адрес открытыми даже после вашего звонка на close.Попробуйте выполнить одно из следующих действий:

  • выполните sleep(10) (или более) между close и вызовом doConnect снова
  • настройте сокеты с помощью setsockoptс выключенным SO_LINGER

Это на самом деле чаще происходит с TCP-соединениями, но я не вижу причин, по которым UDP не может также иметь эту проблему.

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