Получение недопустимого аргумента в качестве причины сбоя при включении опции TCP keep alive?

#linux #tcp #tcp-keepalive

#linux #tcp #tcp-keepalive

Вопрос:

Я попытался реализовать TCP-клиент для отправки запроса TCP keep alive, но все опции были сброшены с недопустимым аргументом. Мой код выглядит так, как показано ниже:

     #define SERVER_ADDRESS "94.23.3.169" /* Server address */
    #define PORT 1010/* the port client will be connecting to */
    
    
    static int16_t i16Sockfd;
    
    void vEnablekeepalive(int16_t i16Sockfd;)
    {
        int16_t i16Enable;
        socklen_t optlen = sizeof(i16Enable);
    
        /* Check the status for the keepalive option */
        if(getsockopt(i16Sockfd, SOL_SOCKET, SO_KEEPALIVE, amp;i16Enable, amp;optlen) < 0) {
            perror("getsockopt");
        }
        MSG("Before KEEP_ALIVE OPTION:%dn",i16Enable);
    
        i16Enable = 1;
        if(setsockopt(i16Sockfd, SOL_SOCKET, SO_KEEPALIVE, amp;i16Enable, sizeof(i16Enable)) == -1){
            perror("setsockopt");
        }
    
        /* Check the status for the keepalive option */
        if(getsockopt(i16Sockfd, SOL_SOCKET, SO_KEEPALIVE, amp;i16Enable, amp;optlen) < 0) {
            perror("getsockopt);
        }
        MSG("After KEEP_ALIVE OPTION:%dn",i16Enable);
    
        int16_t i16Idle = 600;
        if(setsockopt(i16Sockfd, IPPROTO_TCP, TCP_KEEPIDLE, amp;i16Idle, sizeof(i16Idle)) == -1){
            perror("Idle");
        }
    
        int16_t i16Interval = 60;
        if(setsockopt(i16Sockfd, IPPROTO_TCP, TCP_KEEPINTVL, amp;i16Interval, sizeof(i16Interval)) == -1){
            perror("Interval");
        }
    
        int16_t i16Maxcount = 5;
        if(setsockopt(i16Sockfd, IPPROTO_TCP, TCP_KEEPCNT, amp;i16Maxcount, sizeof(i16Maxcount)) == -1){
            perror("Maxcount");
        }
    }
    
    int main()
    {
        struct sockaddr_in their_addr;
        
        if ((i16Sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
            perror("socket");
        }
              
        Enablekeepalive(i16Sockfd);
    
        their_addr.sin_family = AF_INET; /* host byte order */
        their_addr.sin_port = htons(PORT); /* short, network byte order */
        their_addr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
        zero(amp;(their_addr.sin_zero), 8); /* zero the rest of the struct */
        if (connect(i16Sockfd, (struct sockaddr*) amp;their_addr,sizeof(struct sockaddr)) == -1) {
            perror("connect");
            close(i16Sockfd);
        }
              
    }
  

Я не могу понять, почему он выдает недопустимый аргумент для всех setsockopt API. Есть ли что-то неправильное в настройке опции keep alive с помощью setsockopt?

Комментарии:

1. Почему вы используете int16_t для всех мест, требующих int ? Вероятно, они не одинакового размера в вашей системе.

Ответ №1:

SO_KEEPALIVE предназначен для сокета, ориентированного на соединение. Поэтому, пожалуйста, сначала подключите свой сокет и после этого установите SO_KEEPALIVE.

Комментарии:

1. У меня есть еще один вопрос: если я включил keep alive и установил все опции для keep alive, используя приведенный выше код, тогда мне нужно изменить настройки ниже? # echo 600 > /proc/sys /net/ipv4/tcp_keepalive_time # echo 60 > / proc /sys /net/ipv4 /tcp_keepalive_intvl # echo 20 > /proc /sys /net/ipv4/tcp_keepalive_probes

2. @AbhishekLakhara: Вам не нужно изменять настройки, если вы можете жить с текущими настройками. Обратите внимание, что вы также можете применить настройки, зависящие от сокета, для таймингов keep alive — см. tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#setsockopt

Ответ №2:

Из socket(7) документации, которая охватывает SO_XXX параметры сокета:

Перечисленные ниже параметры сокета можно установить с помощью setsockopt(2) и считывать getsockopt(2) с помощью уровня сокета, установленного SOL_SOCKET для всех сокетов. Если не указано иное, optval является указателем на int .

и

SO_KEEPALIVE Включить отправку сообщений keep-alive на сокетах, ориентированных на подключение. Ожидает целочисленный логический флаг.

Параметры и TCP_KEEPIDLE т. Д., Специфичные для Linux, Также ожидают int аргумент.

int16_t Подобный, который вы используете в качестве типа параметра, вряд ли будет того же размера, int что и в обычных системах в наши дни, отсюда и ошибки. Используйте int вместо этого.