【问题标题】:UDP Multicast not receiving messageUDP 组播未收到消息
【发布时间】:2015-11-10 16:19:42
【问题描述】:

我正在尝试制作一个简单的 UDP 多播示例,其中一条消息从一个程序发送并从另一个程序接收,但现在输出仅为:

Connected
Message Sent

bind
setup multicast

有人可以告诉我我缺少什么以便我可以成功接收消息吗?谢谢!!以下是完整的代码:

int main(int argc, char *argv[])
{

int udp_socket_info;
struct sockaddr_in udp_server;
char* message="test";

    //create socket
    udp_socket_info = socket(AF_INET, SOCK_DGRAM, 0);
    if (udp_socket_info == -1) {
    puts("Could not create socket");
    }

//assign local values
    udp_server.sin_addr.s_addr = inet_addr("225.0.0.37"); //multicast address
    udp_server.sin_family = AF_INET;
    udp_server.sin_port = htons( 1100 );

    //checks connection 
    if (connect(udp_socket_info, (struct sockaddr *)&udp_server, sizeof(udp_server)) < 0) {
    perror("Connection error");
    }
    puts("Connected");

    //sends message
    if( sendto(udp_socket_info , message , strlen(message) , 0, (struct sockaddr *)&udp_server, sizeof(udp_server)) < 0) {     
perror("Send failed");
    }
    puts("Message Sent");

}

第二个程序是

int main(int argc, char *argv[])
{

//initialize udp socket and structures
int udp_socket_info;
struct sockaddr_in udp_server;
struct sockaddr addr;
struct ip_mreq mreq;
socklen_t fromlen;
fromlen = sizeof addr;
char incoming_message[100];

    //create udp socket
    udp_socket_info = socket(AF_INET, SOCK_DGRAM, 0);
    if (udp_socket_info == -1) {
    puts("Could not create socket");
        }

    // set up 
memset((char*)&udp_server,0,sizeof(udp_server));
    udp_server.sin_family=AF_INET;
    udp_server.sin_port = htons( 1100 );
udp_server.sin_addr.s_addr = inet_addr("192.168.0.100"); //local address

    // bind 
    if (bind(udp_socket_info,(struct sockaddr *)&udp_server, sizeof(udp_server)) < 0) {
  perror("bind error");
  exit (1);
      }
puts("bind");

 // use setsockopt() to join multicast group
 mreq.imr_multiaddr.s_addr=inet_addr("225.0.0.37"); //multicast address
 mreq.imr_interface.s_addr= htonl(INADDR_ANY); //can use local address here too
 if (setsockopt(udp_socket_info, IPPROTO_IP,IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
  perror("setsockopt");
  exit (1);
      }
puts("setup multicast");

    //Receive an incoming message
    if( recvfrom(udp_socket_info, incoming_message , sizeof(incoming_message), 0, &addr, &fromlen) < 0) {
puts("Received failed");
exit (1);
    }
    puts("Message received");
    puts(incoming_message);
}

【问题讨论】:

  • 您是否尝试过使用网络嗅探程序(例如 Wireshark)来验证发送程序是否正确发送数据包?

标签: c sockets udp multicast


【解决方案1】:

您应该将接收套接字绑定到 INADDR_ANY,而不是本地接口地址。否则,您将面临发件人通过不同路线到达那里并且无法到达您的套接字的风险。在某些平台上,您可以将其绑定到多播地址本身。

注意,当您遇到错误时,仅打印您自己设计的消息是不够的。消息必须包含errno,或strerror() 的结果。例如,拨打perror()

【讨论】:

    【解决方案2】:

    您的接收器不应绑定到本地地址。它应该绑定到INADDR_ANY 或您打算加入的多播地址。绑定到本地地址会中断 Linux 系统上的多播。

    请注意,如果您绑定到一个多播地址,这意味着您将只接收该多播地址的数据包。如果你想从多个多播地址接收,或者你还想接收单播数据包,那么你需要绑定到INADDR_ANY

    加入多播组时,使用 INADDR_ANY 会导致您加入默认网络接口上的指定组。明确指定接口通常是个好主意。

    正如 EJP 所述,您应该始终使用 perror 打印来自任何系统或库调用的错误消息,以确保打印出有意义的错误消息。

    Wireshark 是此类程序的重要工具。它可以帮助您确保数据包在您期望的网络接口中出入。

    另外,如果发送方和接收方位于不同的网段,您需要通过 IP_MULTICAST_TTL 套接字选项设置 TTL。您还需要确保它们之间的任何路由器都配置为传递多播流量。

    【讨论】:

    • VG。它真的会破坏多播吗?我原以为只要您使用相同的 IP 地址进行绑定和加入,并且发件人在该路由上,它应该可以工作。但是我已经很多年没有接触过 Linux 系统了。
    • @EJP 确实如此。我有一个 UFTP 的 Windows 用户请求绑定到特定地址,所以我添加了该功能。对他来说效果很好,但第二天我收到了 Linux 用户的投诉,所以我不得不恢复更改。
    • @EJP:你是对的——它没有。我的 ubuntu 在绑定到多播 IP/端口的套接字上完美接收多播。使用 connect() 后,情况变得严峻。比如说,如果你喜欢在同一个套接字上发送和接收多播数据包,你不能使用 connect() 来设置 dst 多播地址,因为它会阻止你接收,因为在连接的套接字上接收到的数据包必须具有 src addr = connected addr,多播永远不会发生这种情况。
    • @EJP 绑定到多播地址实际上很好。当您绑定到 Linux 有问题的本地地址时。我已经编辑以澄清差异。
    猜你喜欢
    • 2019-05-12
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2012-09-17
    • 2018-08-11
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    相关资源
    最近更新 更多