1

首先,请耐心回答一个很长的问题——我正在编写一个 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() 仅在程序执行的最后被调用,因此它们都是有效的。

4

0 回答 0