Search code examples
cnetwork-programmingudpmulticast

Could not able to do bidirectional multicast connection using UDP


Have to make it server & client as bidirectional where I should able to send & receive data in console.

I can able to send data from server to client but not able to receive any data from client.Stuck in this for long time could not know how to resolve it.

I just started working on networking any lead on this really helpful.

Here is my code.

Server.c

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
struct in_addr localInterface;
struct sockaddr_in groupSock, rcv_addr;
int sd;
char databuf[1024];
int datalen = sizeof(databuf);
int main(int argc, char *argv[])
{

    /* Create a datagram socket on which to send. */
    socklen_t rcv_addr_size = sizeof(struct sockaddr_in);
    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sd < 0)
    {
        perror("Opening datagram socket error");
        exit(1);
    }
    else
        printf("Opening the datagram socket...OK.\n");

    memset((char*) &groupSock, 0, sizeof(groupSock));
    groupSock.sin_family = AF_INET;
    groupSock.sin_addr.s_addr = inet_addr("226.1.1.1");
    groupSock.sin_port = htons(4321);
    localInterface.s_addr = inet_addr("127.0.0.1");

    if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char*) &localInterface,
            sizeof(localInterface)) < 0) {

        perror("Setting local interface error");
        exit(1);
    } else
        printf("Setting the local interface...OK\n");
    int read_size;
    while (1) {
        memset(databuf, 0x00, sizeof(databuf));
        scanf("%s", databuf);
        datalen = strlen(databuf) + 1;
        if (sendto(sd, databuf, datalen, 0, (struct sockaddr*) &groupSock,
                sizeof(groupSock)) < 0)

            datalen = 1024;
        memset(databuf, 0x00, sizeof(databuf));
        read_size = recvfrom(sd, databuf, datalen, 0,
                (struct sockaddr*) &rcv_addr, &rcv_addr_size);
        printf("The message from multicast ckient is: \"%s\"\n", databuf);

    }
    return 0;

}

client.c

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
struct sockaddr_in localSock, rcv_addr;
struct ip_mreq group;
int sd;
int datalen;
char databuf[1024];
int main(int argc, char *argv[]) {
    /* Create a datagram socket on which to receive. */
    socklen_t rcv_addr_size = sizeof(struct sockaddr_in);
    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sd < 0) {
        perror("Opening datagram socket error");
        exit(1);
    }

    else

        printf("Opening datagram socket....OK.\n");

    {
        int reuse = 1;
        if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse,
                sizeof(reuse)) < 0) {
            perror("Setting SO_REUSEADDR error");
            close(sd);
            exit(1);
        } else
            printf("Setting SO_REUSEADDR...OK.\n");
    }
    memset((char*) &localSock, 0, sizeof(localSock));
    localSock.sin_family = AF_INET;
    localSock.sin_port = htons(4321);
    localSock.sin_addr.s_addr = INADDR_ANY;
    if (bind(sd, (struct sockaddr*) &localSock, sizeof(localSock))) {
        perror("Binding datagram socket error");
        close(sd);
        exit(1);
    } else
        printf("Binding datagram socket...OK.\n");
    group.imr_multiaddr.s_addr = inet_addr("226.1.1.1");
    group.imr_interface.s_addr = INADDR_ANY;
    if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &group,
            sizeof(group)) < 0) {
        perror("Adding multicast group error");
        close(sd);
        exit(1);
    } else
        printf("Adding multicast group...OK.\n");
    int read_size;
    while (1) {
        datalen = 1024;
        memset(databuf, 0x00, sizeof(databuf));
        read_size = recvfrom(sd, databuf, datalen, 0,
                (struct sockaddr*) &rcv_addr, &rcv_addr_size);
        printf("The message from multicast server is: \"%s\"\n", databuf);

        memset(databuf, 0x00, sizeof(databuf));
        scanf("%s", databuf);
        datalen = strlen(databuf) + 1;
        if (sendto(sd, databuf, datalen, 0, (struct sockaddr*) &localSock,
                sizeof(localSock)) < 0)
            break;
    }
    return 0;

}

Solution

  • Your server is sending to the wrong address.

    The server is using localSock as the destination address for sendto:

    if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&localSock, sizeof(localSock)) < 0)
    

    But you have that address set to 0:

    localSock.sin_family = AF_INET;
    localSock.sin_port = htons(4321);
    localSock.sin_addr.s_addr = INADDR_ANY;
    

    You want to instead use rcv_addr, which was populated as the source address from recvfrom. Using this address as the destination will send the response back where it came from:

    if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&rcv_addr, sizeof(rcv_addr)) < 0)