UDP unicast, broadcast and multicast

     There is no need to suggest a connection prior to the transmission of information using the UDP protocol. In other words, the client sends information to the server. The client only needs to give the ip address and port number of the server, and then encapsulate the information into a message to be sent and send it out. As for whether the server exists, or whether it can receive the message, the client does not care at all.     

     Unicast is used for end-to-end communication between two hosts, and broadcast is used for data communication from one host to all hosts on the entire local area network. Unicast and broadcast are two extremes, either communicating to one host or communicating to hosts on the entire local area network. In practice, it is often necessary to communicate to a specific set of hosts, rather than all hosts on the entire local area network, and this is what multicasting is for.

  Usually the udp programs we discuss are all one-to-one unicast programs. This chapter will discuss one-to-many services: broadcast, multicast. For broadcasts, all hosts in the network receive a copy of the data. With multicast, the message is simply sent to a multicast address, and the network knows to distribute the data to hosts that say they want to receive data sent to that multicast address. In general, only UDP sockets allow broadcast or multicast.

1. UDP broadcast

  The difference between broadcast UDP and unicast UDP is that the IP address is different. Broadcast uses the broadcast address 255.255.255.255 to send messages to every host on the same broadcast network. It is worth emphasizing that local broadcast information will not be forwarded by routers . Of course, this is very easy to understand, because if the router forwards the broadcast information, it will inevitably cause network paralysis. This is why the designers of the IP protocol deliberately did not define an Internet-wide broadcast mechanism.

Broadcast addresses are often used to communicate status information, etc., among players on the same local network in online games.

  In fact, as the name implies, broadcasting wants to talk to all the people in the local area network, but broadcasting still needs to specify the port number of the receiver , because it is impossible for all ports of the receiver to listen to the broadcast.

UDP server code:

copy code
copy code
1 #include<iostream>
 2 #include<stdio.h>
 3 #include<sys/socket.h>
 4 #include<unistd.h>
 5 #include<sys/types.h>
 6 #include<netdb.h>
 7 #include<netinet/in.h>
 8 #include<arpa/inet.h>
 9 #include<string.h>
10 using namespace std;
11 int main()
12 {
13     setvbuf(stdout,NULL,_IONBF,0);
14     fflush(stdout);
15     int sock=-1;
16     if((sock=socket(AF_INET,SOCK_DGRAM,0))==-1)
17     {
18         cout<<"sock error"<<endl;
19         return -1;
20     }
21     const int opt=-1;
22     int nb=0;
23 nb=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char*)&opt,sizeof(opt));//Set the socket type
24     if(nb==-1)
25     {
26         cout<<"set socket error...\n"<<endl;
27         return -1;
28     }
29     struct sockaddr_in addrto;
30     bzero(&addrto,sizeof(struct sockaddr_in));
31 addrto.sin_family = AF_INET;
32 addrto.sin_addr.s_addr=htonl(INADDR_BROADCAST);//The socket address is the broadcast address
33 addrto.sin_port=htons(6000);//The socket broadcast port number is 6000
34     int nlen=sizeof(addrto);
35     while(1)
36     {
37         sleep(1);
38         char msg[]={"the message broadcast"};
39 int ret=sendto(sock,msg,strlen(msg),0,(sockaddr*)&addrto,nlen);//Publish a message to the broadcast address
40         if(ret<0)
41         {
42             cout<<"send error...\n"<<endl;
43             return -1;
44         }
45         else
46         {
47             printf("ok\n");
48         }
49     }
50     return 0;
51 }
copy code
copy code

 UDP broadcast client code:

copy code
copy code
1 #include<iostream>
 2 #include<stdio.h>
 3 #include<sys/socket.h>
 4 #include<unistd.h>
 5 #include<sys/types.h>
 6 #include<netdb.h>
 7 #include<netinet/in.h>
 8 #include<arpa/inet.h>
 9 #include<string.h>
10 
11 
12 using namespace std;
13 int main()
14 {
15         setvbuf(stdout,NULL,_IONBF,0);
16         fflush(stdout);
17         struct sockaddr_in addrto;
18         bzero(&addrto,sizeof(struct sockaddr_in));
19         addrto.sin_family=AF_INET;
20         addrto.sin_addr.s_addr=htonl(INADDR_ANY);
21         addrto.sin_port=htons(6000);
22         socklen_t len=sizeof(addrto);
23         int sock=-1;
24         if((sock=socket(AF_INET,SOCK_DGRAM,0))==-1)
25         {
26                 cout<<"socket error..."<<endl;
27                 return -1;
28         }
29         const int opt=-1;
30         int nb=0;
31         nb=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char*)&opt,sizeof(opt));
32         if(nb==-1)
33         {
34                 cout<<"set socket errror..."<<endl;
35                 return -1;
36         }
37         if(bind(sock,(struct sockaddr*)&(addrto),len)==-1)
38         {
39                 cout<<"bind error..."<<endl;
40                 return -1;
41         }
42         char msg[100]={0};
43         while(1)
44         {
45                 int ret=recvfrom(sock,msg,100,0,(struct sockaddr*)&addrto,&len);
46                 if(ret<=0)
47                 {
48                         cout<<"read error..."<<endl;
49                 }
50                 else
51                 {
52                         printf("%s\t",msg);
53                 }
54                 sleep(1);
55         }
56         return 0;
57 }
copy code
copy code

 二、UDP多播

1、多播(组播)的概念

  多播,也称为“组播”,将网络中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。

  在广域网上广播的时候,其中的交换机和路由器只向需要获取数据的主机复制并转发数据。主机可以向路由器请求加入或退出某个组,网络中的路由器和交换机有选择地复制并传输数据,将数据仅仅传输给组内的主机。多播的这种功能,可以一次将数据发送到多个主机,又能保证不影响其他不需要(未加入组)的主机的其他通 信。

相对于传统的一对一的单播,多播具有如下的优点:

  1、具有同种业务的主机加入同一数据流,共享同一通道,节省了带宽和服务器的优点,具有广播的优点而又没有广播所需要的带宽。

  2、服务器的总带宽不受客户端带宽的限制。由于组播协议由接收者的需求来确定是否进行数据流的转发,所以服务器端的带宽是常量,与客户端的数量无关。

  3、与单播一样,多播是允许在广域网即Internet上进行传输的,而广播仅仅在同一局域网上才能进行。

组播的缺点:

  1、多播与单播相比没有纠错机制,当发生错误的时候难以弥补,但是可以在应用层来实现此种功能。

  2、多播的网络支持存在缺陷,需要路由器及网络协议栈的支持。

  3、多播的应用主要有网上视频、网上会议等。

2、广域网的多播

  多播的地址是特定的,D类地址用于多播。D类IP地址就是多播IP地址,即224.0.0.0至239.255.255.255之间的IP地址,并被划分为局部连接多播地址、预留多播地址和管理权限多播地址3类:

  1、局部多播地址:在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包。

  2、预留多播地址:在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议。

  3、管理权限多播地址:在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。

  多播的程序设计使用setsockopt()函数和getsockopt()函数来实现,组播的选项是IP层的,其选项值和含义参见11.5所示。

                                  表11.5 多播相关的选项

getsockopt()/setsockopt()的选项

含 义

IP_MULTICAST_TTL

设置多播组数据的TTL值

IP_ADD_MEMBERSHIP

在指定接口上加入组播组

IP_DROP_MEMBERSHIP

退出组播组

IP_MULTICAST_IF

获取默认接口或设置接口

IP_MULTICAST_LOOP

禁止组播数据回送

3、多播程序设计的框架

要进行多播的编程,需要遵从一定的编程框架。多播程序框架主要包含套接字初始化、设置多播超时时间、加入多播组、发送数据、接收数据以及从多播组中离开几个方面。其步骤如下:

(1)建立一个socket。

(2)然后设置多播的参数,例如超时时间TTL、本地回环许可LOOP等。

(3)加入多播组。

(4)发送和接收数据。

(5)从多播组离开。

4、多播实现代码

服务端代码:

copy code
copy code
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<sys/socket.h>
 4 #include<netdb.h>
 5 #include<sys/types.h>
 6 #include<arpa/inet.h>
 7 #include<netinet/in.h>
 8 #include<unistd.h>
 9 #include<stdlib.h>
10 #include<string.h>
11 #define MCAST_PORT 8888
12 #define MCAST_ADDR "224.0.0.88"  // 多播地址
13 #define MCAST_DATA "BROADCAST TEST DATA"  // 多播内容
14 #define MCAST_INTERVAL 5  //多播时间间隔
15 using namespace std;
16 
17 int main()
18 {
19         int sock;
20         struct sockaddr_in mcast_addr;
21         sock=socket(AF_INET,SOCK_DGRAM,0);
22         if(sock==-1)
23         {
24                 cout<<"socket error"<<endl;
25                 return -1;
26         }
27         memset(&mcast_addr,0,sizeof(mcast_addr));
28         mcast_addr.sin_family=AF_INET;
29         mcast_addr.sin_addr.s_addr=inet_addr(MCAST_ADDR);
30         mcast_addr.sin_port=htons(MCAST_PORT);
31         while(1)
32         {       //向局部多播地址发送多播内容
33                 int n=sendto(sock,MCAST_DATA,sizeof(MCAST_DATA),0,(struct sockaddr*)&mcast_addr,sizeof(mcast_addr));
34                 if(n<0)
35                 {
36                         cout<<"send error"<<endl;
37                         return -2;
38                 }
39                 else
40                 {
41                         cout<<"send message is going ...."<<endl;
42                 }
43                 sleep(MCAST_INTERVAL);
44 
45         }
46         return 0;
47 }
copy code
copy code

客户端代码:

copy code
copy code
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 #include<sys/types.h>
 6 #include<unistd.h>
 7 #include<sys/socket.h>
 8 #include<netdb.h>
 9 #include<arpa/inet.h>
10 #include<netinet/in.h>
11 #define MCAST_PORT 8888
12 #define MCAST_ADDR "224.0.0.88" /*一个局部连接多播地址,路由器不进行转发*/
13 #define MCAST_INTERVAL 5  //发送时间间隔
14 #define BUFF_SIZE 256   //接收缓冲区大小
15 using namespace std;
16 int main()
17 {
18         int sock;
19         struct sockaddr_in local_addr;
20         int err=-1;
21         sock=socket(AF_INET,SOCK_DGRAM,0);
22         if(sock==-1)
23         {
24                 cout<<"sock error"<<endl;
25                 return -1;
26         }
27         /*初始化地址*/
28         local_addr.sin_family=AF_INET;
29         local_addr.sin_addr.s_addr=htonl(INADDR_ANY);
30         local_addr.sin_port=htons(MCAST_PORT);
31         /*绑定socket*/
32         err=bind(sock,(struct sockaddr*)&local_addr,sizeof(local_addr));
33         if(err<0)
34         {
35                 cout<<"bind error"<<endl;
36                 return -2;
37         }
38         /*设置回环许可*/
39         int loop=1;
40         err=setsockopt(sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));
41         if(err<0)
42         {
43                 cout<<"set sock error"<<endl;
44                 return -3;
45         }
46         struct ip_mreq mreq;/*加入广播组*/
47         mreq.imr_multiaddr.s_addr=inet_addr(MCAST_ADDR);//广播地址
48         mreq.imr_interface.s_addr=htonl(INADDR_ANY); //网络接口为默认
49         /*将本机加入广播组*/
50         err=setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
51         if(err<0)
52         {
53                 cout<<"set sock error"<<endl;
54                 return -4;
55         }
56         int times=0;
57         socklen_t addr_len=0;
58         char buff[BUFF_SIZE];
59         int n=0;
60         /*循环接受广播组的消息,5次后退出*/
61         for(times=0;;times++)
62         {
63                 addr_len=sizeof(local_addr);
64                 memset(buff,0,BUFF_SIZE);
65                 n=recvfrom(sock,buff,BUFF_SIZE,0,(struct sockaddr*)&local_addr,&addr_len);
66                 if(n==-1)
67                 {
68                         cout<<"recv error"<<endl;
69                         return -5;
70                 }
71                 /*打印信息*/
72                 printf("RECV %dst message from server : %s\n",times,buff);
73                 sleep(MCAST_INTERVAL);
74         }
75         /*退出广播组*/
76         err=setsockopt(sock,IPPROTO_IP,IP_DROP_MEMBERSHIP,&mreq,sizeof(mreq));
77         close(sock);
78         return 0;
79 }
copy code
copy code

 关于此处bind函数的解析

  bind操作首先检查用户指定的端口是否可用,然后为socket的一些成员设置正确的值,并添加到哈希表myudp_hash中。然后,协议栈每次收到UDP数据,就会检查该数据报的源和目的地址,还有源和目的端口,在myudp_hash中找到匹配的socket,把该数据报放入该 socket的接收队列,以备用户读取。在这个程序中,bind操作把socket绑定到地址224.0.0.88:8888上, 该操作产生的直接结果就是,对于socket本身,下列值受影响:
    struct inet_sock{
        .rcv_saddr = 224.0.0.88;
        .saddr = 0.0.0.0;
        .sport = 8888;
        .daddr = 0.0.0.0;
        .dport = 0;
    }
    这五个数据表示,该套接字在发送数据包时,本地使用端口8888,本地可以使用任意一个网络设备接口,发往的目的地址不指定。在接收数据时,只接收发往IP地址224.0.0.88的端口为8888的数据。

我的疑问???

为什么要广播方和接受方的端口号相同才能收到广播?我试了在一台linux机子上开两个客户端其中一个和广播方的端口号不同,这个客户端结果收不到广播,哪位网友知道恳请告之。
    程序中,紧接着bind有一个setsockopt操作,它的作用是将socket加入一个组播组,因为socket要接收组播地址224.0.0.1的数据,它就必须加入该组播组。

三、UDP广播与单播

广播与单播的比较

  The processing process of broadcast and unicast is different. Unicast data is only processed by a specific host that sends and receives data, while broadcast data is processed by the entire local area network.

  For example, there are 3 hosts on an Ethernet, and the configuration of the hosts is shown in Table 11.4.

                                  Table 11.4 Configuration of hosts in a local area network

host

A

B

C

IP address

192.168.1.150

192.168.1.151

192.168.1.158

MAC address

00:00:00:00:00:01

00:00:00:00:00:02

00:00:00:00:00:03

  Unicast process: Host A sends a UDP datagram to host B, the destination IP is 192.168.1.151, the port is 80, and the destination MAC address is 00:00:00:00:00:02. This data passes through the UDP layer and the IP layer, and reaches the data link layer, and the data is spread on the entire Ethernet. In this layer, other hosts will determine the destination MAC address. The MAC address of host C is 00:00:00:00:00:03, which does not match the destination MAC address of 00:00:00:00:00:02. The data link layer will not process it and directly discard the data.

  The MAC address of host B is 00:00:00:00:00:02, which is consistent with the destination MAC address 00:00:00:00:00:02. The data will pass through the IP layer and the UDP layer to reach the application receiving the data. program.

  Broadcast process: Host A sends broadcast data to the entire network, the destination IP is 192.168.1.255, the port is 80, and the destination MAC address is FF:FF:FF:FF:FF:FF. This data passes through the UDP layer and the IP layer, and reaches the data link layer, and the data is spread on the entire Ethernet. In this layer, other hosts will determine the destination MAC address. Since the destination MAC address is FF:FF:FF:FF:FF:FF, host C and host B will ignore the comparison of the MAC address (of course, if the protocol stack does not support broadcasting, the MAC address will still be compared), and process the received data .

  The processing process of host B and host C is the same. The data will pass through the IP layer and the UDP layer to reach the application receiving the data.

 

 

http://www.cnblogs.com/lidabo/p/5865045.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326220974&siteId=291194637