多播/广播

多播

多播组地址:D类IP(具体的还没学)

  1. 发送方设置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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#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;
}

广播

  1. 直接广播
  2. 本地广播 IP:255.255.255.255,给子网所有主机发送传输数据,

和多播不同的是范围

send.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#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 网络编程 尹圣雨>>