EDIT: Problem explanation modified to make it clearer.

我写了两个简单的程序:

  • 客户端程序:将UDP组播数据包发送到组播IP地址和端口 .

  • 服务器程序:请求成员IP的成员资格,绑定到同一端口并使用'recvfrom'接收这些数据包 . 它还将这些数据包的内容与源地址和端口一起打印到控制台上 .

现在,我在Machine_S上启动'server'程序,在Machine_C上启动'client'程序 . 两台机器都在同一个局域网中 .

客户端's multicast packets reach Machine_S, which I am able to see in Wireshark. However, '服务器程序无法读取它们,即对recvfrom的调用不会返回 .

现在,我在Machine_S上启动了另一个'client'实例 . 一旦完成,'服务器'程序就开始从两个客户端(从两台机器)接收数据包并将它们打印到控制台!

此时,即使我关闭Machine_S上的本地“客户端”实例,“服务器”仍将继续从Machine_C上的远程“客户端”接收数据包 .

简而言之,只有当本地客户端也将数据包发送到同一个多播地址和端口时,服务器程序似乎才会从远程客户端接收数据包 .

Client Code:

// COMMON MACROS FOR BOTH CLIENT AND SERVER
#define HELLO_PORT  12345
#define HELLO_GROUP "239.0.0.50"

// after initializing winsock

// create UDP socket
if ((sockid = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {

    printf("SOCKET Error Code: %d\n", WSAGetLastError());
    WSACleanup();
    return 1;
 }


 // set up destination address
 memset(&addr,0,sizeof(addr));
 addr.sin_family        =   AF_INET;
 addr.sin_addr.s_addr   =   inet_addr(HELLO_GROUP);
 addr.sin_port          =   htons(HELLO_PORT);

 // now just sendto() our destination!
 while (times--) {

     printf("Sent To : %d\n", HELLO_PORT);

     if (sendto (sockid, message, strlen(message)+1, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {

         printf("SENDTO Error Code: %d\n", WSAGetLastError());
         break;
     }

    Sleep(500);
 }

 closesocket(sockid);

 WSACleanup();

Server Code:

// create UDP socket
if ((sockid = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {

    printf("SOCKET Error Code: %d\n", WSAGetLastError());
    WSACleanup();
    return 1;
}


// set up local address
memset(&addr,0,sizeof(addr));
addr.sin_family         =   AF_INET;
addr.sin_addr.s_addr    =   htonl (INADDR_ANY);
addr.sin_port           =   htons (HELLO_PORT);

// bind to local address
if (bind(sockid, (struct sockaddr *)&addr, sizeof(addr)) < 0) {

    printf("BIND Error Code: %d\n", WSAGetLastError());
    closesocket(sockid);
    WSACleanup();
    return 1;
}

// join a multicast group 
mreq.imr_multiaddr.s_addr   =   inet_addr (HELLO_GROUP);
mreq.imr_interface.s_addr   =   htonl (INADDR_ANY);         

if (setsockopt(sockid, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq)) < 0) {

    printf("SETSOCKETOPT Error Code: %d\n", WSAGetLastError());
    closesocket(sockid);
    WSACleanup();
    return 1;
}

memset(&addr,0,sizeof(addr));

// now just enter a read-print loop 
while (times--) {

    addrlen =   sizeof(addr);

    if ((nbytes = recvfrom(sockid, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *)&addr, &addrlen)) < 0) {

        printf("RECVFROM Error Code: %d\n", WSAGetLastError());
        break;
    }

    inet_ntop(AF_INET, &(addr.sin_addr), (PSTR)&address, MSGBUFSIZE);
    srcport = ntohs(addr.sin_port);
    printf("From\t%s\t%d\t", address, srcport);
    puts(msgbuf);

    Sleep(1000);
}

closesocket(sockid);
WSACleanup();

几点需要注意:

  • 每台机器只有1个网络接口

  • 多播IP为239.0.0.50,端口为12345

这可能是什么原因?