多播
多播组地址:D类IP(具体的还没学)
- 发送方设置TTL,接收方设置所在多组播组IP
setsockopt,IPPROTO_IP层选项:
IP_MULTICAST_TTL:生存时间(time to live):组播传送距离
IP_ADD_MEMBERSHIP:加入组播
- 多播基于UDP协议完成,对面1000个用户,不需要像TCP建立1000个连接,不需要像UDP1000次数据传输,多播发送一次,由路由器完成包的复制
发送方:./news_sender 224.2.2.2 9190
#include <me.h>
#define TTL 64
#define BUF_SIZE 30
int main(int argc,char *argv[])
{
int send_sock;
struct sockaddr_in mul_adr;
int time_live = TTL;
if (argc != 3)
{
printf("Usage: %s <GroupIp> <PORT> \n",argv[0]);
exit(1);
}
//设置发送方socket,以及TTL
send_sock = socket(AF_INET,SOCK_DGRAM,0);
memset(&mul_adr,0,sizeof(mul_adr));
mul_adr.sin_family = AF_INET;
mul_adr.sin_addr.s_addr = inet_addr(argv[1]);
mul_adr.sin_port = htons(atoi(argv[2]));
setsockopt(send_sock,IPPROTO_IP,IP_MULTICAST_TTL,(void*)&time_live,sizeof(time_live));//设置TTL
//一次性得到消息大小发送过去
struct stat status;
int fd;
fd = open("news.txt",O_RDWR);
fstat(fd,&status);
int len = status.st_size;
char buf[len];
read(fd,buf,len);
sendto(send_sock,buf,len,0,(struct sockaddr*)&mul_adr,sizeof(mul_adr));
close(fd);
close(send_sock);
return 0;
}
接收方./news_receiver 224.2.2.2 9190
#include <me.h>
#define BUF_SIZE 40
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 <GroupIp> <PORT>\n",argv[0]);
exit(1);
}
recv_sock = socket(AF_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_handle("bind() error")
//加入多播组
join_adr.imr_multiaddr.s_addr = inet_addr(argv[1]); //多播组的组IP地址
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);
memset(&buf,0,sizeof(buf));
}
close(recv_sock);
return 0;
}
广播
- 直接广播
- 本地广播 IP:255.255.255.255,给子网所有主机发送传输数据,
和多播不同的是范围
send.c
#include <me.h>
#define BUF_SIZE 30
int main(int argc,char *argv[])
{
int send_sock;
struct sockaddr_in broad_adr;
FILE *fp;
char buf[BUF_SIZE+10];
int so_brd = 1;
if (argc != 3)
{
printf("Usage : %s <Broadcast IP> <PORT>\n",argv[0]);
exit(1);
}
send_sock = socket(AF_INET,SOCK_DGRAM,0);//UDP端口
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]));
//设置socket为广播
setsockopt(send_sock,SOL_SOCKET,SO_BROADCAST,(void*)&so_brd,sizeof(so_brd));
if ((fp = fopen("news.txt","r")) == NULL)
error_handle("fopen() error")
while(!feof(fp))
{
fgets(buf,BUF_SIZE,fp);
sendto(send_sock,buf,strlen(buf),0,(struct sockaddr*)&broad_adr,sizeof(broad_adr));
char ch = fgetc(fp);
if (ch == EOF)
break;
else
sendto(send_sock,&ch,1,0,(struct sockaddr*)&broad_adr,sizeof(broad_adr));
sleep(1);
}
close(send_sock);
return 0;
}
receive.c
#include <me.h>
#define BUF_SIZE 30
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 <PORT> \n",argv[0]);
exit(1);
}
recv_sock = socket(AF_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_handle("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;
}
来自<<TCP/IP 网络编程 尹圣雨>>