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--;
}
}
}
}
|