simple multicast app not working on different computer on the same network

半城伤御伤魂 提交于 2019-12-11 19:04:14

问题


  • If I launch 2 instances of the code below in the same computer the multicast works fine.
  • If I launch it on a different computer in the same network I won't receive anything.

Any idea what could be wrong? This code should compile as is.

I am testing on win10 but I get similar results when I run this on linux.

#include "pch.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "winsock2.h"
#include <iostream>
#include <conio.h>
#include <thread>
#include <ws2tcpip.h>

#pragma comment(lib, "ws2_32.lib")

char mcastGroup[] = "224.1.2.3";
int mcastPort = 5435;

int CreateSocket()
{
    return socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}

void JoinGroup(int sck)
{
    struct ip_mreq grp;
    grp.imr_multiaddr.s_addr = inet_addr(mcastGroup);
    grp.imr_interface.s_addr = htonl(INADDR_ANY);

    if (setsockopt(sck, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&grp, sizeof(grp)) < 0)
    {
        printf("Error in joining group\n");
        closesocket(sck);
        exit(1);
    }
}

int receiver()
{
     int sck = CreateSocket();

    int reuse = 1;
    if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
    {
        perror("Socket reuse address error\n");
        closesocket(sck);
        exit(1);
    }

    JoinGroup(sck);

    struct sockaddr_in lclSck;
    memset((char *)&lclSck, 0, sizeof(lclSck));
    lclSck.sin_family = AF_INET;
    lclSck.sin_port = htons(mcastPort);
    lclSck.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sck, (struct sockaddr*)&lclSck, sizeof(lclSck)))
    {
        perror("Error in binding socket\n");
        closesocket(sck);
        exit(1);
    }

    while (1)
    {
        int blen;
        char buf[1024];
        blen = sizeof(buf);
        memset(buf, 0, blen);

        struct sockaddr_in addrin;
        int addrinlen = sizeof(addrin);
        memset(&addrin, 0, sizeof(addrin));
        int res = recvfrom(sck, buf, blen, 0, (sockaddr *)&addrin, &addrinlen);
        if (res<0)
        {
            printf("Message read error\n");
            closesocket(sck);
            exit(1);
        }
        else
        {
            printf(": %s\n", buf);
        }

    }
    return 0;
}

int sender()
{
    int sck = CreateSocket();

    struct in_addr lclInterface;
    lclInterface.s_addr = htonl(INADDR_ANY);
    if (setsockopt(sck, IPPROTO_IP, IP_MULTICAST_IF, (char *)&lclInterface, sizeof(lclInterface)) < 0)
    {
        printf("Local interface error\n");
        exit(1);
    }
    else
    {
        printf("Local interface set\n");
    }

    u_char ttl = 5;
    setsockopt(sck, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));

    while (1)
    {
        int blen;
        char buf[1024];
        blen = sizeof(buf);
        memset(buf, 0, blen);

        for (int i = 0; i < 100; i++)
        {
            fgets(buf, blen, stdin);

            sockaddr_in grpSck;
            memset((char *)&grpSck, 0, sizeof(grpSck));
            grpSck.sin_family = AF_INET;
            grpSck.sin_port = htons(mcastPort);
            grpSck.sin_addr.s_addr = inet_addr(mcastGroup);
            if (sendto(sck, buf, blen, 0, (struct sockaddr*)&grpSck, sizeof(grpSck)) < 0)
            {
                printf("Error in sending message");
            }
        }
    }
    return 0;
}

int main()
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    std::thread t1([&] { receiver(); return 0; });   
    sender();

    WSACleanup();
}

回答1:


This code should work, the problem was that I was using IP_MULTICAST_IF, that forces to use a network interface different from the default one. In case one needs to use such a thing I was able to get the multicast working by following Thanks to Remy Lebeau advice, that is to make sure you are binding the sockets to IPs that are in the same network.

Here is working code the code:

#ifdef WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

#else
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>

#endif

#include <thread>

char mcastGroup[] = "224.1.2.3";
int mcastPort = 5435;

void PrintAddrIn(sockaddr_in addr_in)
{
    char str[255];
    inet_ntop(AF_INET, &addr_in.sin_addr, (char *)str, sizeof(str));
    printf("%s", str);
}

int receiver(int sck)
{
    while (1)
    {
        char buf[1024];
        memset(buf, 0, sizeof(buf));

        struct sockaddr_in addrin;
        socklen_t addrinlen = sizeof(addrin);
        memset(&addrin, 0, sizeof(addrin));
        int res = recvfrom(sck, buf, sizeof(buf), 0, (sockaddr *)&addrin, &addrinlen);
        if (res<0)
        {
            printf("Message read error\n");
            exit(1);
        }
        else
        {
            PrintAddrIn(addrin); printf(": %s\n", buf);
        }
    }
    return 0;
}

int sender(int sck)
{
    while (1)
    {
        sockaddr_in grpSck;
        memset((char *)&grpSck, 0, sizeof(grpSck));
        grpSck.sin_family = AF_INET;
        grpSck.sin_port = htons(mcastPort);
        grpSck.sin_addr.s_addr = inet_addr(mcastGroup);

        for (int i = 0; i < 100; i++)
        {
            char buf[1024];
            fgets(buf, sizeof(buf), stdin);

            if (sendto(sck, buf, strlen(buf), 0, (struct sockaddr*)&grpSck, sizeof(grpSck)) < 0)
            {
                printf("Error in sending message");
                exit(1);
            }
        }
    }
    return 0;
}

int main()
{
#ifdef WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif

    int sck = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    // Set reuse
    //
    int reuse = 1;
    if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
    {
        perror("Socket reuse address error\n");
        exit(1);
    }
    else
    {
        printf("Socket reuse address successfull\n");
    }

    // Join mcast group
    //
    struct ip_mreq grp;
    grp.imr_multiaddr.s_addr = inet_addr(mcastGroup);
    grp.imr_interface.s_addr = htonl(INADDR_ANY);
    if (setsockopt(sck, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&grp, sizeof(grp)) < 0)
    {
        printf("Error in joining group\n");
        exit(1);
    }
    else
    {
        printf("Group joined successfully\n");
    }

    // Bind socket
    //
    struct sockaddr_in lclSck;
    memset((char *)&lclSck, 0, sizeof(lclSck));
    lclSck.sin_family = AF_INET;
    lclSck.sin_port = htons(mcastPort);
    lclSck.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sck, (struct sockaddr*)&lclSck, sizeof(lclSck)))
    {
        perror("Error in binding socket\n");
        exit(1);
    }
    else
    {
        printf("Socket binding successfull\n");
    }

    u_char ttl = 5;
    setsockopt(sck, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));

    std::thread t1([&] { receiver(sck); return 0; });

    sender(sck);

#ifdef WIN32
    WSACleanup();
#endif
}


来源:https://stackoverflow.com/questions/57192547/simple-multicast-app-not-working-on-different-computer-on-the-same-network

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!