为什么 recvfrom() returns 错误的发件人地址?
Why does recvfrom() returns wrong address of sender?
这个简单的 UDP 客户端:
#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] = '[=11=]';
puts(recvline);
}
}
将向 127.0.0.1:9877 上的服务器(echo 服务器)发送数据报。输出是
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
您看不到传递的服务器地址 sendto()
(servaddr
) 和来自 recvfrom()
(replyaddr
) 的地址都不是本地主机或 127.0.0.1
.什么是 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
这个是对的,可以看到localhost。那么什么是2.0.38.149
?
地址 2.0.38.149 不是随机的。我可以编译它并 运行 它多次并总是得到相同的地址,2.0.38.149。那个地址是什么?
编辑,服务器部分:
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));
}
您向 inet_ntop
传递了错误的信息。
当inet_ntop
的第一个参数是AF_INET
时,第二个参数应该是指向struct in_addr
的指针。您传递的是指向 struct sockaddr_in
的指针。因此,您看到的值来自 struct sockaddr_in
.
的前 4 个字节
您需要像这样调用包装函数:
Inet_ntop(&servaddr.sin_addr)
这个简单的 UDP 客户端:
#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] = '[=11=]';
puts(recvline);
}
}
将向 127.0.0.1:9877 上的服务器(echo 服务器)发送数据报。输出是
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
您看不到传递的服务器地址 sendto()
(servaddr
) 和来自 recvfrom()
(replyaddr
) 的地址都不是本地主机或 127.0.0.1
.什么是 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
这个是对的,可以看到localhost。那么什么是2.0.38.149
?
地址 2.0.38.149 不是随机的。我可以编译它并 运行 它多次并总是得到相同的地址,2.0.38.149。那个地址是什么?
编辑,服务器部分:
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));
}
您向 inet_ntop
传递了错误的信息。
当inet_ntop
的第一个参数是AF_INET
时,第二个参数应该是指向struct in_addr
的指针。您传递的是指向 struct sockaddr_in
的指针。因此,您看到的值来自 struct sockaddr_in
.
您需要像这样调用包装函数:
Inet_ntop(&servaddr.sin_addr)