如何解决如何使用connect()获取内核分配给UDP套接字的本地地址?
阅读https://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551,章节
8.14 确定与 UDP 的传出接口
连接的 UDP 套接字也可用于确定将要发送的传出接口 用于特定目的地。这是因为连接的副作用 应用于 UDP 套接字时的功能:内核选择本地 IP 地址 (假设进程还没有调用 bind 来显式分配它)。这个本地 通过在路由表中搜索目标 IP 地址来选择 IP 地址,并且 然后将主 IP 地址用于生成的接口。
如果我尝试运行示例 (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,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",cliaddr.sin_port);
}
现在,如果我在一个终端(地址为 INADDR_ANY
和端口为 9877
)中运行服务器,然后运行上面的客户端:
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
即使客户端在打印其地址和端口之前,我总是得到一些垃圾,连接到正在侦听的服务器。如果我试图打印服务器地址和端口,那么它会工作(也就是说,它会分别打印 127.0.0.1:9877
和 10.0.0.11:9877
-> 我已经尝试过)。所以我知道 inet_ntop
工作正常并且还获得了端口号。那么客户端的问题在哪里?内核真的根据书中的connect()
分配地址和端口吗?如果是这样,那么为什么我的示例会打印随机垃圾?
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
解决方法
您正在将 struct sockaddr_in
的地址传递给 inet_ntop
函数。对于 AF_INET
套接字,它需要一个指向 struct in_addr
的指针。
所以不是这样:
inet_ntop(AF_INET,&cliaddr,ip,BSIZE);
你想要这个:
inet_ntop(AF_INET,&cliaddr.sin_addr,BSIZE);
另外,请务必在打印之前对 ntohs
成员调用 sin_port
以获得正确的值,并使用 %d
而不是 %hd
:
printf("address %s:%d\n",ntohs(cliaddr.sin_port));
并且 clilen
未正确初始化:
clilen = sizeof(clilen);
应该是:
clilen = sizeof(cliaddr);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。