This simple UDP client:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define PORT 9877
#define BSIZE 256
#define ADDRSTRLEN 19
static char presentation[ADDRSTRLEN];
char *Inet_ntop(const void *src)
{
if (inet_ntop(AF_INET, src, presentation, ADDRSTRLEN) == NULL)
{
perror("inet_ntop");
}
return presentation;
}
int main()
{
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
char recvline[BSIZE], sendline[BSIZE];
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
//localhost
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
socklen_t servlen = sizeof(servaddr);
struct sockaddr *replyaddr = malloc(servlen);
socklen_t replylen;
while (fgets(sendline, BSIZE, stdin) != NULL)
{
sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *)&servaddr, servlen);
printf("serv addr: %s\n", Inet_ntop(&servaddr));
//recvfrom() should return address of the host this UDP received datagram from (localhost)
replylen = servlen;
ssize_t bytesRead = recvfrom(sockfd, recvline, BSIZE, 0, replyaddr, &replylen);
printf("reply addr: %s\n", Inet_ntop(replyaddr));
recvline[bytesRead] = '\0';
puts(recvline);
}
}
will send datagram to server (echo server) on 127.0.0.1:9877. The output is
a
serv addr: 2.0.38.149
reply addr: 2.0.38.149
a
b
serv addr: 2.0.38.149
reply addr: 2.0.38.149
b
c
serv addr: 2.0.38.149
reply addr: 2.0.38.149
c
^C
you can see neither the server address passed sendto()
(servaddr
) nor the address from recvfrom()
(replyaddr
) is not localhost or 127.0.0.1
. what is 2.0.38.149
??
tcpdump:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
IP 127.0.0.1.40270 > 127.0.0.1.9877: UDP, length 2
IP 127.0.0.1.9877 > 127.0.0.1.40270: UDP, length 2
IP 127.0.0.1.40270 > 127.0.0.1.9877: UDP, length 2
IP 127.0.0.1.9877 > 127.0.0.1.40270: UDP, length 2
IP 127.0.0.1.40270 > 127.0.0.1.9877: UDP, length 2
IP 127.0.0.1.9877 > 127.0.0.1.40270: UDP, length 2
^C
6 packets captured
12 packets received by filter
0 packets dropped by kernel
this is correct, and you can see localhost. So what is 2.0.38.149
?
The address 2.0.38.149 is not random. I can compile it and run it multiple time and always get the same address, 2.0.38.149. What is that address?
EDIT, server part:
void dg_echo(int sockfd, struct sockaddr *cliaddr, socklen_t clilen)
{
ssize_t bytesRead;
socklen_t len;
char buf[BSIZE];
while (1)
{
len = clilen;
bytesRead = Recvfrom(sockfd, buf, BSIZE, 0, cliaddr, &len);
Sendto(sockfd, buf, bytesRead, 0, cliaddr, len);
}
}
int main()
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(sockfd, (SA *)&servaddr, sizeof(servaddr));
dg_echo(sockfd, (SA *)&cliaddr, sizeof(cliaddr));
}
You're passing the wrong thing to inet_ntop
.
When the first parameter to inet_ntop
is AF_INET
, the second parameter should be a pointer to a struct in_addr
. What you're passing in is a pointer to a struct sockaddr_in
. So the values you're seeing are from the first 4 bytes of the struct sockaddr_in
.
You need to call your wrapper function like this:
Inet_ntop(&servaddr.sin_addr)