首先请向我提出一个很长的问题 - 我正在编写一个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;
}
}
//....
neighbors是一个结构数组,其元素具有成员字段:
struct addrinfo *servinfo, *p;
它们是从套接字初始化获得的,而freeaddrinfo()仅在程序执行结束时调用,因此它们都是有效的。