简体   繁体   English

无法从Linux计算机将UDP发送到多播组

[英]Unable to send UDP to a multicast group from a linux computer

I am trying to send a UDP-datagram to an IP camera from a computer running on Linux in order to discover it. 我正在尝试从Linux上运行的计算机向IP摄像机发送UDP数据报以便发现它。 All devices are connected via a switch. 所有设备都通过开关连接。

There is a windows app that is compatible with this camera, that sends out a UDP datagram to a multicast group and gets an answer from the camera via the same group. 有一个与此摄像头兼容的Windows应用程序,该应用程序将UDP数据报发送到多播组,并通过同一组从摄像头获取答案。 I found out this via Wireshark and decided to try and send the same datagram from a C program on my Linux machine. 我通过Wireshark发现了这一点,并决定尝试从Linux机器上的C程序发送相同的数据报。 I am able to get the correct response if my C program sends it directly to the camera's IP-address, but not if I send it to the multicast group. 如果我的C程序将其直接发送到摄像机的IP地址,则能够得到正确的响应,但是如果将其发送到多播组,则无法获得正确的响应。

I therefor made a listener program on my Linux computer and tried to send it to the multicast address. 为此,我在Linux计算机上制作了一个侦听器程序,并尝试将其发送到多播地址。 This succeeded, but I did not catch anything in Wireshark. 这成功了,但是我在Wireshark中什么也没发现。

So it seems that my C-program is able to send the datagram correctly, just not out on to the network. 因此,看来我的C程序能够正确发送数据报,只是无法发送到网络上。 Can this be some kind of Linux configuration? 这可以是某种Linux配置吗?

EDIT: As requested, here is the code. 编辑:根据要求,这是代码。 FYI: As of now, I am only trying to send data to the camera and examine the response in Wireshark. 仅供参考:到目前为止,我仅尝试将数据发送到相机并检查Wireshark中的响应。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>

#include "udp_socket.h"



int main( void )
{

    //int s = udp_socket(50000);
    int s = socket(AF_INET,SOCK_DGRAM,0);
    printf("Socket: %d\r\n", s);


    char buffer[48] = {0x67,0x45,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x67,0x45,0x00,0x00,0x14,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0xea,0xc8,0xc8,0xc8,0xf4,0xe6,0x00,0x00};
    struct sockaddr_in serveraddr;
    memset( &serveraddr, 0, sizeof(serveraddr) );
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons( 59125 );              
    serveraddr.sin_addr.s_addr = inet_addr("234.200.200.200");

    udp_socket_tx(s, buffer, sizeof(buffer), &serveraddr );

    close(s);
}

udp_socket_tx() from udp_socket.h: 来自udp_socket.h的udp_socket_tx():

int udp_socket_tx(int socket_fd, char * tx_buffer, int tx_buffer_len, const struct sockaddr_in * to_addr) {

return sendto(
    socket_fd,
    tx_buffer,
    tx_buffer_len,
    0,
    (const struct sockaddr *)to_addr,
    sizeof(struct sockaddr_in)
);

}

The following proposed code: 建议的代码如下:

  1. cleanly compiles. 干净地编译。
  2. performs the desired operation (sending a UDP packet). 执行所需的操作(发送UDP数据包)。
  3. properly checks the returned status of the call to sendto() . 正确检查sendto()调用的返回状态。
  4. properly checks the returned status of the call to socket() . 正确检查对socket()的调用返回的状态。
  5. does not include header files those contents are not used. 不包括头文件,不使用那些内容。
  6. expects the multicast address to be in the system 'route' table. 期望多播地址在系统的“路由”表中。
  7. respects the width of the printed page 尊重打印页面的宽度
  8. adds the missing #include for the call to printf() . 将缺少的#include添加到对printf()的调用中。
  9. adds the missing #include for the call to memset() . 将缺少的#include添加到memset()的调用中。
  10. properly outputs error messages to stderr 正确将错误消息输出到stderr

and now the proposed code: 现在建议的代码:

#include <stdio.h>      // perror(), printf()
#include <stdlib.h>     // exit(), EXIT_FAILURE, EXIT_SUCCESS
#include <string.h>     // memset()
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>


int main( void )
{
    int s = socket(AF_INET,SOCK_DGRAM,0);
    if ( 0 > s )
    {
        perror( "socket failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, socket successful

    printf("Socket: %d\r\n", s);

    unsigned char buffer[] =
    {
        0x67, 0x45,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,
        0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00, 0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x67,0x45,
        0x00, 0x00,0x14,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,
        0xea, 0xc8, 0xc8, 0xc8, 0xf4, 0xe6, 0x00, 0x00
    };

    struct sockaddr_in serveraddr;
    memset( &serveraddr, 0, sizeof(serveraddr) );
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons( 59125 );
    serveraddr.sin_addr.s_addr = inet_addr("234.200.200.200");

    ssize_t sendtoStatus = sendto
    (
        s,
        buffer,
        sizeof(buffer),
        0,
        (const struct sockaddr *)&serveraddr,
        sizeof(struct sockaddr_in)
    );

    if( -1 == sendtoStatus )
    {
        perror( "sendto failed" );
        close(s);
        exit( EXIT_FAILURE );
    }

    close(s);
    return EXIT_SUCCESS;
} // end function: main

When sending multicast datagrams, they will normally be sent out on whichever network interface is considered the default interface. 发送多播数据报时,通常会在被视为默认接口的任何网络接口上将其发送出去。

If that's not the interface you want to send on, you need to configure the outgoing multicast interface. 如果那不是您要发送的接口,则需要配置传出多播接口。 This is done with the IP_MULTICAST_IF option: 这是通过IP_MULTICAST_IF选项完成的:

If for example you want to send multicast from the interface with IP 192.168.1.1, you set it up as follows: 例如,如果要从IP为192.168.1.1的接口发送多播,请按以下步骤进行设置:

struct in_addr multi_interface;
multi_interface.s_addr = inet_addr("192.168.1.1");
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
               (char *)&multi_interface, sizeof(multi_interface)) == -1) {
    perror("Error setting outgoing interface");
    close(s);
    exit(1);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM