当客户端和服务器位于单独的计算机上时,getsockname()不会返回正确的地址

时间:2019-06-05 03:16:04

标签: sockets posix

我有以下客户端和服务器:

客户:

@Override
public List<SrityDTO> getByCommonColumn(int id) throws Exception {
    Optional<main> ntOptional = ntRepository.findById(id);

    if (ntOptional.isPresent()) {

        List<rity> rities = rityRepository.findByntDomain(ntOptional.get());
        return rities.stream()
                     .map(SrityDTO::new)
                     .collect(Collectors.toList());
    } else {    
        throw new Exception(" not exist.");
    }
}

服务器:

#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;
}

这是一台服务器,用于发送有关客户端和服务器IP地址的客户端信息。当客户端和服务器在同一台计算机上运行时,我获得了服务器IP地址的正确值,但是当我尝试在通过以太网电缆连接的两台单独的计算机上运行客户端和服务器时,我得到了零。另外,无论我做什么,我的客户端IP地址都为零(我无法确定这是正确的还是错误的)。为什么会发生这种情况,我该如何解决?

1 个答案:

答案 0 :(得分:3)

man getpeername明确指出(强调我的意思)

  

address_len参数应该初始化为指示地址指向的空间量。返回时,它包含返回地址的实际大小(以字节为单位)。

     

如果提供的缓冲区太小,地址将被截断。

也就是说,

    socklen_t len = sizeof(struct sockaddr_in);

应该解决问题。