1. 多播,同时向多个主机传递数据
a. 多播服务器针对特定多播组,只发送一次数据;
b. 虽只发送一次数据,但是该组内的所有客户端都会接收数据;
c. 多播组数可以在IP地址范围内任意增加;
d. 加入特定组即可接收发送该多播组的数据。
多播是基于MBone这个虚拟网络工作的,它是以物理网络为基础,通过软件方法实现的多播通信必备虚拟网络。
多播组是D类IP地址,224.0.0.0-239.255.255.255
2. TTL time to live:用整数表示,每经过一个路由器减一,变零时销毁。
int send_sock;
int time_live = 64;
....
setsockopt(send_sock,IPPROTO_IP,IP_MULTICAST_TTL,(void *)&time_live,sizeof(time_live))
3.
加入多播组
struct ip_mreq join_adr;
join_adr.imr_multiaddr.s_addr = "多播组地址信息"
join_adr.imr_interface.s_addr = "加入多播组的主机地址信息"
setsockopt(recv_sock,IPPROTO_IP,IP_ADDR_MEMBERSHIP,(void *)&join_adr,sizeof(join_adr))
4. 示例,多播发送与接收
sender.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 30
#define TTL 64
void error_handling(char *message);
int main(int argc, char *argv[]){
int send_sock;
FILE *fp;
char buf[BUF_SIZE];
struct sockaddr_in mul_adr;
int time_live = TTL;
if(argc != 3){
printf("Usage : %s <group><port>\n",argv[0]);
exit(1);
}
send_sock = socket(PF_INET,SOCK_DGRAM,0);
if(send_sock == -1){
error_handling("socket() error");
}
memset(&mul_adr,0,sizeof(mul_adr));
mul_adr.sin_family=AF_INET;
mul_adr.sin_addr.s_addr=inet_addr(argv[1]); //multi ip
mul_adr.sin_port=htons(atoi(argv[2])); //port
setsockopt(send_sock,IPPROTO_IP,IP_MULTICAST_TTL,(void *)&time_live,sizeof(time_live));
if((fp = fopen("news.txt","r")) == NULL){
error_handling("fopen");
}
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);
fputs("\n",stderr);
exit(1);
}
执行结果:
alex@alex-virtual-machine:/extra/tcpip$ ./sender 224.1.1.2 9190
alex@alex-virtual-machine:/extra/tcpip$
receiver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#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 <group><port>\n",argv[0]);
exit(1);
}
recv_sock = socket(PF_INET,SOCK_DGRAM,0);
if(recv_sock == -1){
error_handling("socket() error");
}
memset(&adr,0,sizeof(adr));
adr.sin_family=AF_INET;
adr.sin_addr.s_addr=htonl(INADDR_ANY); //multi ip
adr.sin_port=htons(atoi(argv[2])); //port
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);
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);
fputs("\n",stderr);
exit(1);
}
执行结果:
alex@alex-virtual-machine:/extra/tcpip$ ./recevier 224.1.1.2 9190
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>