I'm using:
struct in_addr ip;
#define HOST_PORT atoi(argv[2])
#define HOST_IP inet_aton(argv[1], &ip)
sockaddr_in sockaddr;
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = htonl(HOST_IP);
sockaddr.sin_port = htons(HOST_PORT);
To get the ip and port numbers in cli. Then i bind, listen, accept and read.
I do compile and when i use ./server localhost 8080 everything is working as intended.
But if i use ./server 127.0.0.1 8080 or ./server 192.168.30.1 8080 seems like is bind and listening, no errors but i don't recive the request.
inet_aton()
.You are assigning the return value of inet_aton()
to your sockaddr
variable, rather than assigning the in_addr
struct that inet_aton()
outputs. The return value is NOT an IP address!
inet_aton()
returns a non-zero value on success, and 0 on failure. In other words, its return value is basically a boolean value.
Calling bind()
with an IP address of 0.0.0.0
(aka INADDR_ANY
) instructs it to bind an AF_INET
socket to all local network interfaces on the specified port, which is very common (and generally preferred) for a server to do.
Calling inet_aton("localhost")
fails because you can't pass a hostname to inet_aton()
, so it returns 0, and then you bind()
the socket using a sockaddr_in
whose s_addr
is set to INADDR_ANY
, which is OK, so your code seems to work with "localhost"
, but only as a fluke.
Calling inet_aton("127.0.0.1")
or inet_aton("192.168.30.1")
succeeds, so it returns non-zero, and then you bind()
the socket using a sockaddr_in
whose s_addr
is set to an invalid IP, causing bind()
to either fail outright, or worse to bind to an existing network interface that is different than the one you are expecting.
Also, the in_addr
that inet_aton()
outputs is already in network byte order, so there is no need to call htonl()
on its output.
Try this instead:
struct in_addr ip;
#define HOST_PORT atoi(argv[2])
#define HOST_IP ((inet_aton(argv[1], &ip) != 0) ? ip.s_addr : 0)
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = HOST_IP;
sockaddr.sin_port = htons(HOST_PORT);
// use sockaddr as needed ...
Or, simply get rid of your HOST_IP
and HOST_PORT
macros, as they are not really helping you:
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
inet_aton(argv[1], &(sockaddr.sin_addr));
sockaddr.sin_port = htons(atoi(argv[2]));
// use sockaddr as needed ...
That being said, you really should be using getaddrinfo()
instead, eg:
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(argv[1], argv[2], &hints, &res) == 0)
{
// use res->ai_addr and res->ai_addrlen with socket() and bind() as needed ...
freeaddrinfo(res);
}
getaddrinfo()
will parse both IP address strings and hostname strings into appropriate sockaddr_...
structs for you, and will happily handle strings that are related to the local host, like "localhost"
, "127.0.0.1"
, "192.168.30.1"
, etc.