getsockname () не возвращает правильный адрес, когда клиент и сервер находятся на разных компьютерах - PullRequest
0 голосов
/ 05 июня 2019

У меня есть следующие клиент и сервер:

Клиент:

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

int main( int argc, char **argv ){
    int sockfd;
    struct sockaddr_in servaddr;
    memset( &servaddr, 0, sizeof( servaddr ) );
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons( 2000 );
    inet_pton( AF_INET, argv[1], &(servaddr.sin_addr) );
    sockfd = socket( AF_INET, SOCK_STREAM, 0 );
    if( connect( sockfd, (struct sockaddr *) &servaddr, sizeof( servaddr ) ) == -1 ){
            perror( "Client connection error: " );
            exit( errno );
    }
    struct sockaddr_in addr[2];
    recv( sockfd, addr, sizeof( struct sockaddr_in ) * 2, 0 );
    char addr_str_cli[16];
    char addr_str_srv[16];
    memset( addr_str_cli, 0, 16 );
    memset( addr_str_srv, 0, 16 );
    inet_ntop( AF_INET, &(addr[0].sin_addr), addr_str_cli, 16 );
    inet_ntop( AF_INET, &(addr[1].sin_addr), addr_str_srv, 16 );
    printf( "Client: %s\nServer:%s\n", addr_str_cli, addr_str_srv );
    close( sockfd );
    return 0;
}

Сервер:

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

int main( int argc, char **argv ){
    int sockfd, connfd;
    struct sockaddr_in servaddr;
    memset( &servaddr, 0, sizeof( servaddr ) );
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons( 2000 );
    servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
    sockfd = socket( AF_INET, SOCK_STREAM, 0 );
    bind( sockfd, (struct sockaddr *) &servaddr, sizeof( servaddr ) );
    listen( sockfd, 5 );
    if( (connfd = accept( sockfd, (struct sockaddr *) 0, 0 )) == -1 ){
            perror( "Can't open server socket: " );
            exit( errno );
    }
    struct sockaddr_in addr[2];
    socklen_t len;
    memset( addr, 0, sizeof( struct sockaddr_in ) * 2 );
    getpeername( connfd, (struct sockaddr *) &(addr[0]), &len );
    getsockname( connfd, (struct sockaddr *) &(addr[1]), &len );
    send( connfd, addr, sizeof( struct sockaddr_in ) * 2, 0 );
    close( connfd );
    close( sockfd );
    return 0;
}

Данный фрагмент кода следующий:

struct sockaddr_in addr[2];
socklen_t len;
memset( addr, 0, sizeof( struct sockaddr_in ) * 2 );
getpeername( connfd, (struct sockaddr *) &(addr[0]), &len );
getsockname( connfd, (struct sockaddr *) &(addr[1]), &len );
send( connfd, addr, sizeof( struct sockaddr_in ) * 2, 0 );

Это сервер, который отправляет клиенту информацию об IP-адресах клиента и сервера.Когда клиент и сервер работают на одном компьютере, я получаю правильное значение для IP-адреса сервера, но когда я пытаюсь запустить клиент и сервер на двух отдельных компьютерах, соединенных кабелем Ethernet, я получаю ноль.Кроме того, я получаю ноль для IP-адреса клиента, независимо от того, что я делаю (я не могу сказать, правильно ли это или также ошибка).Почему это происходит и как я могу это исправить?

1 Ответ

3 голосов
/ 05 июня 2019

man getpeername четко утверждает, что (выделено мое)

Параметр address_len должен быть инициализирован для указания количества места , на которое указывает адрес. По возвращении он содержит фактический размер возвращаемого адреса (в байтах).

Адрес усекается, если предоставленный буфер слишком мал.

То есть

    socklen_t len = sizeof(struct sockaddr_in);

должен решить проблему.

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