首先,请耐心回答一个很长的问题——我正在编写一个 UDP 客户端-服务器程序,奇怪的是,每当我将这个标志用于协议族时,我都会遇到这个丢包问题。症状是数据包从未离开发送方主机(没有从 tcpdump 捕获),但 sendto() 返回正确的正值,该值永远不会大于 200 字节。我花了很长时间才弄清楚这可以通过强制 IPv4 来解决,但我不明白为什么?它已经在服务器和客户端运行在同一系统(科学 linux 6)上进行了多次测试,因此常见的不可靠 UDP 传输可能不是这里的原因,也没有任何防火墙规则可以丢弃任何东西。我想知道是否有人碰巧知道原因?
我还考虑过发布一些代码,但似乎没有必要。简单地说,AF_UNSPEC 导致所有 UDP 数据包永远不会离开发送者但没有错误,并且使用 AF_INET 一切都很完美。这可能是一个奇怪的问题,但任何见解都值得赞赏。非常感谢!
服务器初始化代码:
int udp_srv_init(char * port)
{
struct addrinfo hints, *servinfo, *p;
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return EXIT_FAILURE;
}
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((self_udp = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("socket");
continue;
}
if (bind(self_udp, p->ai_addr, p->ai_addrlen) == -1) {
close(self_udp);
fprintf(stderr, "Port %s: ",port);
perror("bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "server: failed to bind socket\n");
return EXIT_FAILURE;
}
freeaddrinfo(servinfo);
int buffsize = 65536; // I added this because I thought it was some buffer problem, but didn't change a thing
setsockopt(self_udp, SOL_SOCKET, SO_RCVBUF, (void*)&buffsize, sizeof(buffsize));
return EXIT_SUCCESS;
}
并发送:
//...
for(i=0; i<num_neighbors; i++)
{
if(neighbors[i].cost == -1)
continue;
int bytes_sent = 0, ret;
while(bytes_sent < packet_size)
{
if(-1 == (ret = sendto(neighbors[i].skt, (void*)&my_neighs +
(ptrdiff_t)bytes_sent, packet_size-bytes_sent,
0, neighbors[i].p->ai_addr, neighbors[i].p->ai_addrlen)))
{
perror("sendto1");
return EXIT_FAILURE;
}
bytes_sent += ret;
}
}
//....
邻居是一个结构数组,其元素具有成员字段:
struct addrinfo *servinfo, *p;
它们是从套接字初始化中获得的,并且 freeaddrinfo() 仅在程序执行的最后被调用,因此它们都是有效的。