我正在编写一个非常小的C UDP客户端。我知道当您向服务器发送数据时,会选择随机端口作为源端口。我也知道你可以使用bind来指定自己想要响应的端口。
但是,我不知道什么时候随机选择端口?例如,我想依靠发件人地址来跟踪用户。它目前只有在客户端没有关闭时才有效,端口仍然相同,然后一个简单的memcmp就足以检测到同一个客户端。
这个小代码将使用相同的源端口,直到它退出:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
int main(void)
{
int s, error, ch;
struct addrinfo hints, *res;
memset(&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
if ((error = getaddrinfo("localhost", "9988", &hints, &res)))
errx(1, "%s", gai_strerror(error));
if ((s = socket(res->ai_family, res->ai_socktype, 0)) < 0)
err(1, "socket");
while ((ch = fgetc(stdin)) != EOF)
sendto(s, &ch, 1, 0, res->ai_addr, res->ai_addrlen);
}
运行类似:dmesg | ./client将使用相同的地址,直到程序退出。但是,当您再次运行它时,端口是不同的。
选择端口的套接字函数是什么?还是系统?是否确定端口在客户端生命周期内仍然是相同的?
答案 0 :(得分:3)
如果未明确绑定套接字,则在发送第一个数据包时,操作系统将绑定它(使用随机端口)。只要套接字打开,此绑定就会处于活动状态,一旦关闭套接字(当然)未绑定。
由于UDP套接字的无连接特性,“服务器”(如果正确完成)不应该保留无限期发送给它的所有“客户端”的地址。相反,它应该使用recvfrom
调用中收到的源地址,并将其用于回复。存储源地址不仅仅是一个简单的请求/响应的唯一原因是,如果你有一个更高级的协议在UDP之上,你自己的“连接”处理。