Client server connection on loopback interface

2019-08-21 23:41发布

I'm trying to test a client-server simple implementation using localhost address. Here's the code.

Server:

/*
 * Sequential busy-waiting
 */
int main(int argc, char** argv) {

    int opt, client_addr_l, errsv;
    unsigned short port;
    struct sockaddr_in server_addr, client_addr;

    /* ... */

    printf("Port number retrieved (%d), server is starting ...\n", port);

    /*TCP Socket creation*/
    sock_ds = socket(AF_INET, SOCK_STREAM, 0); 
    if(sock_ds == -1){
        fprintf(stderr, "Socket creation error: %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

    /*Server address binding*/
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = INADDR_ANY;

   /*!!!! */
   int optval = 1;                                      
   if( (setsockopt(sock_ds,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval))) == -1 ) {                
       printf("Error on setsockopt\n");                         
       exit(EXIT_FAILURE);                                  
   }
  /*????*/

   if(bind(sock_ds, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
       fprintf(stderr, "Address binding error\n");
       exit(EXIT_FAILURE);
   }

   /*Server with passive socket*/
   if(listen(sock_ds, SOMAXCONN) == -1){
       fprintf(stderr, "Listen call error: %s\n", strerror(errno));
       exit(EXIT_FAILURE);
   }

   while(1){
       memset(&client_addr, 0, sizeof(client_addr));
       acc_sock_ds = accept(sock_ds, (struct sockaddr *)&client_addr, &client_addr_l);
       printf("DEBUG: LINE201, acc_sock_ds = %d\n", acc_sock_ds);
       /*Connect error management*/
       if(acc_sock_ds == -1){
           fprintf(stderr, "Fatal error on accept %d(%s)\n"
                   , errsv, strerror(errsv));
            exit(EXIT_FAILURE);
       }

       //sin_addr to ASCII (string) );
       printf("Connected with: %s\n", inet_ntoa(client_addr.sin_addr)); 

       /*...*/     

       close(acc_sock_ds);

      /*...*/
    }

/*...*/

}

Client:

 int main(){

    int sock_ds;
    struct sockaddr_in remote_addr;
    struct hostent *hp;

    /*TCP Socket creation*/
    sock_ds = socket(AF_INET, SOCK_STREAM, 0); 
    if(sock_ds == -1){
        fprintf(stderr, "Socket creation error\n");
        exit(EXIT_FAILURE);
    }

    remote_addr.sin_family = AF_INET;
    remote_addr.sin_port = htons(25556);

    hp = gethostbyname("localhost");
    bcopy(hp -> h_addr, &remote_addr.sin_addr, hp -> h_length); //fills address entry

   if(connect(sock_ds, (struct sockaddr*)&remote_addr, sizeof(remote_addr)) == -1){ //connection attempt
       fprintf(stderr, "Connect failure(%s)\n", strerror(errno));
       exit(EXIT_FAILURE);        
   }

   /*...*/

}

When i run them on two different terminals server returns me:

Port number retrieved (25556), server is starting ...
Server is ready. Waiting for client connections.
DEBUG: LINE201, acc_sock_ds = 4
Connected with: 0.0.0.0

My question is: why does the client address retrieved by the server is 0.0.0.0. It should not be 127.0.0.1?

4条回答
太酷不给撩
2楼-- · 2019-08-21 23:48

0.0.0.0 means that your server accept connection from any interface in your equipment

so the loopback interface with the address 127.0..0.1 is included

查看更多
Root(大扎)
3楼-- · 2019-08-21 23:53

It seems to be a special situation. All possible addresses are listening for your connection. Here is a thread on this.

Quote:

0.0.0.0, in this context, means "all IP addresses on the local machine" 
(in fact probably, "all IPv4 addresses on the local machine"). 
So, if your webserver machine has two ip addresses, 192.168.1.1 and 10.1.2.1, 
and you allow a webserver daemon like apache to listen on 0.0.0.0, 
it will be reachable at both of those IPs. 
But only to what can contact those IPs and the web port(s).
查看更多
聊天终结者
4楼-- · 2019-08-22 00:00

It looks like you are passing the third parameter to accept() uninitialized, it should be set at the size of the second parameter. In addition to that, it should be a socklen_t, not an int, see http://pubs.opengroup.org/onlinepubs/009695399/functions/accept.html

Could try by declaring client_addr_l as a socklen_t, then setting it to sizeof( struct sockaddr_in) before passing to accept() ?

I'm guessing its unitialized value is zero, so accept() cannot set the remote address to your client_addr as it has a zero size. So, client_addr is untouched and, as you zeroed it earlier, you get 0.0.0.0.

查看更多
孤傲高冷的网名
5楼-- · 2019-08-22 00:11
server_addr.sin_addr.s_addr = INADDR_ANY;

probably should be

server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
查看更多
登录 后发表回答