1

I am writing a server-client program and in the server I use getaddrinfo and getsockname on the server to get info about the local IP addr and locally bound port number . Using this info, I start my client program and use the getaddrinfo and then just print out the returned values in the servinfo data structure: getaddrinfo(argc[1], argc[2], &hints, &servinfo); >> server hostname and server port number are passed via command line.

But I notice that the sin_port in servinfo is not the port I am passing via the command line. 1) Does this getaddrinfo return the port number being used by the client as the source port number ? 2) My connect call after the getaddrinfo and socket calls in failing. I do not know why. How do I debug it ?

My client code snippet:

memset(&hints, 0 ,sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags =  AI_CANONNAME | AI_NUMERICSERV;
getaddrinfo(argc[1], argc[2], &hints, &servinfo);

for (p = servinfo till p!=NULL)
    sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)
    connect(sockfd, p->ai_addr, p->ai_addrlen) >>>>> Connect not going through.

I start my client program like this: ./a.out myservername 18844

Thanks !

Vin
  • 717
  • 1
  • 12
  • 26
  • How do you know that getaddrinfo() didn't fail with an error? You aren't checking its return value to see if it is zero or not. If gettaddrinfo() failed, then of course it won't have written data to its output argument. – Jeremy Friesner Sep 26 '11 at 16:26
  • I am invoking it with the servername. But missed it add it in the problem description. – Vin Sep 26 '11 at 16:41
  • I shall check the return code from getaddrinfo. It shouldn't be failing since I am able to read the IPv4 address being returned in servinfo structure. – Vin Sep 26 '11 at 16:42
  • I got the problem. sin_port should be converted using ntohl/ntohs and the right port number should be used. Even on the server, I used to get the port number wrong. I converted it to ntohs and used it in the client to connect to the server. So the issue was not converting the sin_port port number from network byte order to a usable form on both server and client. Thanks for all the responses. They helped. – Vin Sep 26 '11 at 18:34

1 Answers1

5

New answer: You are invoking your program with only one argument, so argv[1] contains "18844" and argv[2] is a null pointer. This is going to try to connect to a host with numeric IP 18844 and an unspecified port number (which will end up being 0 and failing).

Old answer: (relevant but not your problem) sin_port and the whole sockaddr_in structure is in network byte order. You'll need to convert the port with ntohl to use it as a number, but you would be better off never touching sockaddr structures' internals whatsoever. Instead, use getnameinfo with NI_NUMERICHOST and NI_NUMERICSERV to get the address back into a string-based numeric form, then strtol to read the port ("service") number into an integer. This works even for non-IPv4 network address/protocol families (like IPv6) and requires no additional code for supporting new ones.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Not to mention that `argc` is not the name that's usually used for the `argv` array. – Michael Burr Sep 26 '11 at 16:33
  • I shall try that. But is the sin_port the client port ? Or should it be same as the server port which I pass through the command line ? Sorry, I am so confused. – Vin Sep 26 '11 at 16:47
  • You pass p->ai_addr to connect() so it will be used as the address to connect *to* , the address of the server. As mentioned, run your code through strace and you should see the arguments connect() is called with. – nos Sep 26 '11 at 16:53
  • Thanks Nos. IP addr is fine. I understand that. I am asking about the sin_port which I am thinking is the client port which will be used by the client as the source port for any communication with the server. But I need someone to clarify this though. – Vin Sep 26 '11 at 16:54
  • @Vin Same thing. The port is part of the address. If you pass "18844" as the 2. argument to your getaddrinfo, that'll get parsed as the port and returned in the p->ai_addr structure (in network byte order, mind you). And the port in the connect() call is the remote/server port. it is not the source port. – nos Sep 26 '11 at 16:57
  • I got the problem. sin_port should be converted using ntohl/ntohs and the right port number should be used. Even on the server, I used to get the port number wrong. I converted it to ntohs and used it in the client to connect to the server. So the issue was not converting the sin_port port number from network byte order to a usable form on both server and client. Thanks for all the responses. They helped. – Vin Sep 26 '11 at 18:34
  • 1
    @Vin: You are better off converting the `sin_port` to text with `getnameinfo()`, as R. describes. – caf Sep 27 '11 at 07:13