LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Source Specific Multicast not working (https://www.linuxquestions.org/questions/programming-9/source-specific-multicast-not-working-715502/)

firsten 03-30-2009 10:03 AM

Source Specific Multicast not working
 
Hi Everyone!
It's been two weeks that i started with network programming using multicasting. I have a server which sends a simple message to a group and all clients who join it receives the message. It all works fine when the clients are in the same subnet as the server. When i try to send it over the internet, specifying the source, nothing happens, and the client does not receive anything at all. It seems that the router is discarding the packages for some reason that i dont know. Can anyone help me? The code of the server and client are presented as follows:

Server
Code:

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


using namespace std;

/* Not everyone has the headers for this so improvise */
#ifndef MCAST_JOIN_SOURCE_GROUP
#define MCAST_JOIN_SOURCE_GROUP 46

struct group_source_req
{
        /* Interface index.  */
        uint32_t gsr_interface;

        /* Group address.  */
        struct sockaddr_storage gsr_group;

        /* Source address.  */
        struct sockaddr_storage gsr_source;
};
#endif


int main(int argc, char *argv[])
{
        struct group_source_req group_source_req;
        struct sockaddr_in *group;
        struct sockaddr_in *source;
        int sockfd = socket(AF_INET,SOCK_DGRAM,getprotobyname("udp")->p_proto);
        socklen_t socklen = sizeof(struct sockaddr_storage);
        struct sockaddr_in bindaddr;
        u_char loop = 1;
                int ret;
                int flag = 1;
                char frame[23] = "Mensagem Multicast!!!!";
               

        /* First bind to the port */
        bindaddr.sin_family = AF_INET;
        bindaddr.sin_port = htons(7125);
        bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);

                ret = bind(sockfd,(struct sockaddr*)&bindaddr,sizeof(bindaddr));

                if (ret < 0){
                        perror("bind(fd,(struct sockaddr*)&bindaddr,sizeof(bindaddr))");
                        return(-1);
                }
        /* Now set up the SSM request */
        group_source_req.gsr_interface = 0; /* "any" interface */
        group=(struct sockaddr_in*)&group_source_req.gsr_group;
        source=(struct sockaddr_in*)&group_source_req.gsr_source;

        group->sin_family = AF_INET;
        inet_aton("232.1.1.1",&group->sin_addr);
        group->sin_port = 0;    /* Ignored */

        /* Set the source to the name of the socket we created above */
        ret = getsockname(sockfd,(struct sockaddr *)source, &socklen);

                if (ret < 0){
                        perror("getsockname(fd,(struct sockaddr *)source, &socklen)");
                        return(-1);
                }

        ret = setsockopt(sockfd,SOL_IP,MCAST_JOIN_SOURCE_GROUP, &group_source_req,
                                sizeof(group_source_req));

                if (ret < 0){
                        perror("setsockopt(fd,SOL_IP,MCAST_JOIN_SOURCE_GROUP, &");
                        return(-1);
                }
        /* Enable reception of our own multicast */
        loop = 1;
       
                ret = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
               
                if (ret < 0){
                        perror("setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP");
                        return(-1);
                }
        /* Set the TTL on packets to 250 */
        loop=64;
        ret = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &loop, sizeof(loop));

                if (ret < 0){
                        perror("setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL");
                        return(-1);
                }

        /* Now we care about the port we send to */
        group->sin_port = htons(7125);

                int i = 1;

        /* Now send packets */
                while (flag){

                        ret = sendto(sockfd, frame, strlen(frame), 0, (sockaddr*) group, sizeof(struct sockaddr_in));
               
                        if (ret < 0){
                                perror("sendto(");
                                return(-1);
                        }

                        sleep(1);       

                        cout << "Enviando " << i << endl;
               
                        i++;

                }
        return 0;
}

Client

Code:

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


using namespace std;

/* Not everyone has the headers for this so improvise */
#ifndef MCAST_JOIN_SOURCE_GROUP
#define MCAST_JOIN_SOURCE_GROUP 46

struct group_source_req
{
        /* Interface index.  */
        uint32_t gsr_interface;

        /* Group address.  */
        struct sockaddr_storage gsr_group;

        /* Source address.  */
        struct sockaddr_storage gsr_source;
};
#endif

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

                // Variáveis do Cliente
        struct group_source_req group_source_req;
        struct sockaddr_in *group;
        struct sockaddr_in *source;
        int sockfd = socket(AF_INET,SOCK_DGRAM,getprotobyname("udp")->p_proto);
        struct sockaddr_in bindaddr;
                //struct sockaddr_in sock_rcvd_id;
            socklen_t size_source;
                int ret;
                int flag = 1;
                char frame[23] = "Mensagem Multicast!!!!";

                // Variáveis do Select
                int maxfdp1 = 1;
                int fd_aux;
                fd_set fd_rset;
                FD_ZERO( &fd_rset);
                fd_set fd_rset_aux;
                FD_ZERO( &fd_rset_aux);
                timeval timeout;
                int n, h;

        /* Setup the socket to listen on */
        bindaddr.sin_family = AF_INET;
        bindaddr.sin_port = htons(7125);
        bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        ret = bind(sockfd,(struct sockaddr*)&bindaddr,sizeof(bindaddr));
               
                if (ret < 0){
                        perror("bind(sockfdfd,(struct sockaddr*)&bindaddr,sizeof(bindaddr))");
                        return(-1);
                }

        /* Set up the connection to the group */
        group_source_req.gsr_interface = 0;
        group=(struct sockaddr_in*)&group_source_req.gsr_group;
        source=(struct sockaddr_in*)&group_source_req.gsr_source;
        /* Group is 232.1.1.1 */
        group->sin_family = AF_INET;
        inet_aton("232.1.1.1",&group->sin_addr);
        group->sin_port = 0;

        /* Source is 150.162.19.139 */
        source->sin_family = AF_INET;
        inet_aton(argv[1],&source->sin_addr);
        source->sin_port = 0;
                size_source = sizeof(&source);

        ret = setsockopt(sockfd,SOL_IP,MCAST_JOIN_SOURCE_GROUP, &group_source_req,
                                sizeof(group_source_req));

                if (ret < 0){
                        perror("setsockopt(sockfd,SOL_IP,MCAST_JOIN_SOURCE_GROUP,");
                        return(-1);
                }

                // Incui o socket na lista de sockets monitorados pelo select
                fd_aux = sockfd + 1;
                if ( maxfdp1 < fd_aux) maxfdp1 = fd_aux;
                        FD_SET(sockfd, &fd_rset);

        while(flag) {

                        // Configura o select
                        FD_ZERO( &fd_rset_aux);
                        fd_rset_aux = fd_rset;
                        timeout.tv_sec = 0;
                        timeout.tv_usec = 2000000; // 2s
                       
                        // verifica se recebeu mensagens no socket indicado, caso contrario escreve "timeout"
                        n = select (maxfdp1, &fd_rset_aux, NULL, NULL, &timeout);

                        if (n < 0){

                                perror("select (maxfdp1, ");
                                return(-1);
                                               
                        }

                        if (!n){
       
                                cout << "timeout!" << endl;

                        } else {

                                while (n>0) {
                       
                                //int len = 65534;
                                char buffer[65534];
                                //h = recvfrom(sockfd,frame,len,MSG_DONTWAIT | MSG_WAITALL,(sockaddr*) &source , &size_source);
                                h = recv(sockfd,(char*)buffer,sizeof(buffer),0);
                               
                                if (h < 0 ){

                                        perror("recvfrom");
                                        return(-1);
                                               
                                }

                                cout << frame << endl;
                               
                                n--;

                                       
                                }

                        }

                }


}



All times are GMT -5. The time now is 10:38 AM.