多播
多播方式的数据传输是基于UDP完成的。区别在于UDP数据传输以单一目标进行,而多播数据同时传递到加入(注册)特定组的大量主机。采用多播方式可以同时向多个主机传递数据。
多播的数据传输方式特点int send_sock;
int time_live=64;
....
send_sock=socket(PF_INET,SOCK_DGRAM,0);
setsockopt(send_sock,IPPROTO_IP,TP_MULTICAST_TTL,(void*)&time_live);
sizeof(time_live);
....
另外,加入多播组也通过设置套接字选项完成。加入多播组相关的协议层为IPPROTO_IP,选项名为IP_ADD_MEMBERSHIP。可通过如下代码加入多播组。
int recv_sock;
struct ip_mreq join_adr;
....
recv_sock=socket(PF_INET,SOCK_DGRAM,0);
....
join_adr.imr_multiaddr.s_addr="多播组地址信息";
join_adr.imr_interface.s_addr="加入多播组的主机地址信息";
setsockopt(recv_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(void*)&join_adr);
sizeof(join_adr);
....
下面是ip_mreq结构体,该结构体定义如下:
struct ip_mreq
{
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
}
第一个成员imr_multiaddr写入加入的组IP地址。
#include
#include
#include
#include
#include
#include
#define TTL 64
#define BUF_SIZE 30
void error_handling(char *message);
int main(int argc,char **argv)
{
int send_sock;
struct sockaddr_in mul_adr;
int time_live=TTL;
FILE *fp;
char buf[BUF_SIZE];
if(argc!=3){
printf("Usage:%s \n",argv[0]);
exit(1);
}
send_sock=socket(PF_INET,SOCK_DGRAM,0);//创建UDP套接字
memset(&mul_adr,0,sizeof(mul_adr));
mul_adr.sin_family=AF_INET;
mul_adr.sin_addr.s_addr=inet_addr(argv[1]); //多播IP
mul_adr.sin_port=htons(atoi(argv[2])); //多播端口
setsockopt(send_sock,IPPROTO_IP,IP_MULTICAST_TTL,(void*)&time_live,sizeof(time_live));//指定TTL信息
if((fp=fopen("news.txt","r"))==NULL)
error_handling("fopen() error");
while(!feof(fp)){
fgets(buf,BUF_SIZE,fp);
sendto(send_sock,buf,strlen(buf),0,(struct sockaddr*)&mul_adr,
sizeof(mul_adr));
sleep(2);
}
fclose(fp);
close(send_sock);
return 0;
}
void error_handling(char *message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
Receiver:
#include
#include
#include
#include
#include
#include
#define TTL 64
#define BUF_SIZE 30
void error_handling(char *message);
int main(int argc,char **argv)
{
int recv_sock;
int str_len;
char buf[BUF_SIZE];
struct sockaddr_in adr;
struct ip_mreq join_adr;
if(argc!=3){
printf("Usage:%s\n",argv[0]);
exit(1);
}
recv_sock=socket(PF_INET,SOCK_DGRAM,0);
memset(&adr,0,sizeof(adr));
adr.sin_family=AF_INET;
adr.sin_addr.s_addr=htonl(INADDR_ANY);
adr.sin_port=htons(atoi(argv[2]));
if(bind(recv_sock,(struct sockaddr*)&adr,sizeof(adr))==-1)
error_handling("bind() error");
join_adr.imr_multiaddr.s_addr=inet_addr(argv[1]);//初始化多播组地址
join_adr.imr_interface.s_addr=htonl(INADDR_ANY); //初始化待加入主机的IP地址
setsockopt(recv_sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(void*)&join_adr,sizeof(join_adr));//加入多播组
while(1)
{
str_len=recvfrom(recv_sock,buf,BUF_SIZE-1,0,NULL,0);
if(str_len<0)
break;
buf[str_len]=0;
fputs(buf,stdout);
}
close(recv_sock);
return 0;
}
void error_handling(char *message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
int send_sock;
int bcast=1; //对变量进行初始化以将SO_BROADCAST选项信息改为1
....
send_sock=socket(PF_INET,SOCK_DGRAM,0);
....
setsockopt(send_sock,SOL_SOCKET,SO_BROADCAST,(void*)&bcast,sizeof(bcast));
调用setsockopt函数,将SO_BROADCAST选项设置为bcast变量中的值1。这意味着可以进行数据广播。
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 30
void error_handling(char *message);
int main(int argc,char **argv)
{
int send_sock;
struct sockaddr_in broad_adr;
FILE* fp;
char buf[BUF_SIZE];
int so_brd=1;
if(argc!=3){
printf("Usage :%s \n",argv[0]);
exit(1);
}
send_sock=socket(PF_INET,SOCK_DGRAM,0);
memset(&broad_adr,0,sizeof(broad_adr));
broad_adr.sin_family=AF_INET;
broad_adr.sin_addr.s_addr=inet_addr(argv[1]);
broad_adr.sin_port=htons(atoi(argv[2]));
setsockopt(send_sock,SOL_SOCKET,SO_BROADCAST,(void*)&so_brd,sizeof(so_brd));
if((fp=fopen("news.txt","r"))==NULL)
error_handling("fopen() error");
while(!feof(fp)){
fgets(buf,BUF_SIZE,fp);
sendto(send_sock,buf,strlen(buf),0,
(struct sockaddr*)&broad_adr,sizeof(broad_adr));
sleep(2);
}
close(send_scok);
return 0;
}
void error_handling(char *message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
Receiver:
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 30
void error_handling(char *message);
int main(int argc,char **argv)
{
int recv_sock;
struct sockaddr_in adr;
int str_len;
char buf[BUF_SIZE];
if(argc!=2){
printf("Usage :%s \n",argv[0]);
exit(1);
}
recv_sock=socket(PF_INET,SOCK_DGRAM,0);
memset(&adr,0,sizeof(adr));
adr.sin_family=AF_INET;
adr.sin_addr.s_addr=htonl(INADDR_ANY);
adr.sin_port=htons(atoi(argv[1]));
if(bind(recv_sock,(struct sockaddr*)&adr,sizeof(adr))==-1)
error_handling("bind() error");
while(1){
str_len=recvfrom(recv_sock,buf,BUF_SIZE-1,0,NULL,0);
if(str_len<0)break;
buf[str_len]=0;
fputs(buf,stdout);
}
close(recv_sock);
return 0;
}
void handling(char *message)
{
fputs(message,stderr);
fputc('\0',stderr);
exit(1);
}