Reputation: 1965
Reading the https://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551, chapter
8.14 Determining Outgoing Interface with UDP
A connected UDP socket can also be used to determine the outgoing interface that will be used to a particular destination. This is because of a side effect of the connect function when applied to a UDP socket: The kernel chooses the local IP address (assuming the process has not already called bind to explicitly assign this). This local IP address is chosen by searching the routing table for the destination IP address, and then using the primary IP address for the resulting interface.
If I try to run the example (udpcli01.c):
#define BSIZE 256
#define SERV_PORT 9877
typedef struct sockaddr SA;
//argv[1] = ip address
int main(int argc, char **argv)
{
int sockfd;
socklen_t servlen, clilen;
struct sockaddr_in cliaddr, servaddr;
char ip[BSIZE];
if (argc < 2)
{
die("usage: %s <ip>\n", argv[0]);
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
servlen = sizeof(servaddr);
memset(&servaddr, 0, servlen);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
connect(sockfd, (SA *)&servaddr, servlen);
clilen = sizeof(clilen);
if (getsockname(sockfd, (SA *)&cliaddr, &clilen) < 0)
{
perror("getsockname");
}
inet_ntop(AF_INET, &cliaddr, ip, BSIZE);
printf("address %s:%hd\n", ip, cliaddr.sin_port);
}
Now If i run the server in one terminal (which address INADDR_ANY
and port 9877
), and then run the client above:
terminal 1:
$ ./udpserv01
terminal 2:
$ #I will try localhost first
$ ./udpcli01 127.0.0.1
address 2.0.178.211:-11342
$ #did not work, now my host ip 10.0.0.11
$ ./udpcli01 10.0.0.11
address 2.0.193.86:22209
I always get some garbage even if the client is prior to printing its address and port, connected to server, which is listening. If i was trying to print server address and port, then it would work (that is, it would print 127.0.0.1:9877
and 10.0.0.11:9877
respectively -> I have already tried). So I know the inet_ntop
is working correctly and also getting the port number. So where is issue in the client? Does the kernel really assigns address and port upon connect()
according to the book? If so then why my example prints random garbage?
uname -a:
Linux Shepherd 5.8.0-36-generic #40-Ubuntu SMP Tue Jan 5 21:54:35 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Upvotes: 2
Views: 1020
Reputation: 225007
You're passing the address of a struct sockaddr_in
to the inet_ntop
function. For an AF_INET
socket it expects a pointer to a struct in_addr
.
So instead of this:
inet_ntop(AF_INET, &cliaddr, ip, BSIZE);
You want this:
inet_ntop(AF_INET, &cliaddr.sin_addr, ip, BSIZE);
Also, be sure to call ntohs
on the sin_port
member before you print it to get the proper value, and use %d
instead of %hd
:
printf("address %s:%d\n", ip, ntohs(cliaddr.sin_port));
And clilen
is not initialized properly:
clilen = sizeof(clilen);
It should be:
clilen = sizeof(cliaddr);
Upvotes: 2