简体   繁体   中英

Correct way to get a socket's peer IP address on MacOS

I'm trying this simple code, to get the client's IP address. It works nice on FreeBSD, but strangely returns zeroes on MacOS. I'm confused and can't understand what's wrong.

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

int main() {
    int s, c;
    socklen_t len;
    struct sockaddr_in saddr, caddr;

    if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        printf("socket()\n"); exit(1);
    }
    
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(9090);

    if ((bind(s, (struct sockaddr *)&saddr, sizeof(saddr))) != 0) {
        printf("bind()\n"); exit(1);
    }

    if ((listen(s, 5)) != 0) {
        printf("listen()\n"); exit(1);
    }

    if ((c = accept(s, (struct sockaddr *)&caddr, &len)) < 0) {
        printf("accept()\n"); exit(0);
    }

    char ipstr[INET6_ADDRSTRLEN];
    inet_ntop(AF_INET, &caddr.sin_addr, ipstr, len);
    
    printf("Client IP address: [%s:%d]\n", ipstr, ntohs(caddr.sin_port));

    close(c);  close(s);

    return 0;
}

On FreeBSD:

Client IP address: [127.0.0.1:17225]

On MacOS:

Client IP address: [0.0.0.0:0]

You must initialize len before calling accept . It tells accept the size of the structure passed to it:

len = sizeof caddr;
if ((c = accept(s, (struct sockaddr *)&caddr, &len)) < 0) { ... }

If it's not initialized it will have an indeterminate (read: garbage) value which could lead to undefined behavior .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM