网络通信:单播、广播、组播
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 網(wǎng)絡(luò)通信:單播、廣播、組播
本文文件夾:
一、網(wǎng)絡(luò)通信的分類、他們的定義和特點(diǎn)。
二、單播、廣播、組播的傳輸信息的網(wǎng)絡(luò)拓?fù)淠P汀?/span>
三、單播、廣播、組播的編程實(shí)例。
一、網(wǎng)絡(luò)通信的分類、他們的定義和特點(diǎn)。
二、單播、廣播、組播的傳輸信息的網(wǎng)絡(luò)拓?fù)淠P汀?/strong>
(一)單播
如圖8-1 所看到的,網(wǎng)絡(luò)中存在信息發(fā)送者Source,UserA 和UserC 提出信息需求,網(wǎng)絡(luò)採用單播方式傳輸信息。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
單播傳輸特點(diǎn)歸納例如以下:
* Source 向每一個(gè)Receiver 地址發(fā)送一份獨(dú)立的拷貝信息:packets for UserA;packets for UserC。
* 網(wǎng)絡(luò)為每一個(gè)Receiver 分別建立一條獨(dú)立的數(shù)據(jù)傳送通路:Source→ RouterB → RouterE → RouterD → UserA;Source → RouterB → RouterE → RouterF → UserC。
單播方式下,網(wǎng)絡(luò)中傳輸?shù)男畔⒘亢托枨笤撔畔⒌挠脩袅砍烧?#xff0c;當(dāng)需求該信息的用戶量較大時(shí),網(wǎng)絡(luò)中將出現(xiàn)多份同樣信息流。此時(shí),帶寬成為保證網(wǎng)絡(luò)傳輸質(zhì)量的重要瓶頸。
單播方式較適合用戶稀少的網(wǎng)絡(luò),不利于信息規(guī)模化發(fā)送。
(二)廣播
如圖8-2 所看到的,網(wǎng)絡(luò)中存在信息發(fā)送者Source,UserA 和UserC 提出信息需求,網(wǎng)絡(luò)採用廣播方式傳輸信息。
? ? ? ? ? ? ? ? ? ? ? ? ? ??
廣播傳輸特點(diǎn)歸納例如以下:
* Source 向本網(wǎng)絡(luò)廣播地址發(fā)送且僅發(fā)送一份報(bào)文:packets for all the network。
* 網(wǎng)絡(luò)將報(bào)文拷貝傳送到全部網(wǎng)段,無論是否須要,保證信息到達(dá)網(wǎng)絡(luò)中全部的路由器和用戶:UserB 也相同接收到一份拷貝。
廣播方式下,網(wǎng)絡(luò)中全部用戶都能接收到該信息,當(dāng)網(wǎng)絡(luò)中需求該信息的用戶量非常小時(shí),網(wǎng)絡(luò)資源利用率將非常低,帶寬浪費(fèi)嚴(yán)重。不須要這些信息的用戶也會(huì)受到影響。
廣播方式較適合用戶稠密的網(wǎng)絡(luò),信息安全性和有償服務(wù)得不到保障。?
(三)多播
如圖8-3 所看到的,網(wǎng)絡(luò)中存在信息發(fā)送者Source、UserA 和UserC 提出信息需求,網(wǎng)絡(luò)採用組播方式傳輸信息。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
組播傳輸特點(diǎn)歸納例如以下:
* Multicast group 稱為組播組,使用一個(gè)IP 組播地址標(biāo)識(shí)。UserA 和UserC 兩個(gè)信息接收者,增加該組播組,從而能夠接收發(fā)往該組播組的數(shù)據(jù)。
* Source 稱為組播源,向該組播組地址發(fā)送且僅發(fā)送一份報(bào)文:packets for the multicast group。網(wǎng)絡(luò)傳輸過程中,同樣的組播數(shù)據(jù)流在每一條鏈路上最多僅有一份。相比單播來說,使用組播方式傳遞信息,用戶的添加不會(huì)顯著添加網(wǎng)絡(luò)的負(fù)載。
* 依據(jù)組播組成員的分布情況,組播路由協(xié)議為多目的端的數(shù)據(jù)包轉(zhuǎn)送建立樹型路由。報(bào)文在盡可能遠(yuǎn)的分叉路口(如RouterE)才開始復(fù)制和分發(fā),終于傳送到組播組成員。相比廣播來說,組播數(shù)據(jù)僅被傳輸?shù)接薪邮照叩牡胤?#xff0c;不會(huì)造成網(wǎng)絡(luò)資源的浪費(fèi)。
* 網(wǎng)絡(luò)中支持組播功能的路由器稱為“組播路由器”,不僅提供組播路由功能,還可以在與網(wǎng)絡(luò)用戶連接的末梢網(wǎng)段上提供組成員管理功能(如RouterD 和RouterF)。同一時(shí)候,自己本身也可能是組播組成員。
* 組播組中的成員是動(dòng)態(tài)的,網(wǎng)絡(luò)中的用戶主機(jī)能夠在不論什么時(shí)刻增加和離開組播組。組成員可能廣泛分布在網(wǎng)絡(luò)中的不論什么地方。組播源通常不會(huì)同一時(shí)候是其發(fā)送數(shù)據(jù)的接收者,即不屬于其相應(yīng)的目的組播組。
* 一個(gè)源能夠同一時(shí)候向多個(gè)組播組發(fā)送數(shù)據(jù);多個(gè)源能夠同一時(shí)候向一個(gè)組播組發(fā)送報(bào)文。
* 為了幫助理解,能夠類比收看某電視頻道的節(jié)目。
* 組播組是發(fā)送者和接收者之間的一個(gè)約定,如同電視頻道。
* 電視臺(tái)是組播源,它向某頻道內(nèi)發(fā)送數(shù)據(jù)。
* 電視機(jī)是接收者主機(jī),觀眾打開電視機(jī)選擇收看某頻道的節(jié)目,表示主機(jī)增加某組播組;然后電視機(jī)播放該頻道電視節(jié)目,表示主機(jī)接收到發(fā)送給這個(gè)組的數(shù)據(jù)。
* 觀眾能夠隨時(shí)控制電視機(jī)的開關(guān)和頻道間的切換,表示主機(jī)動(dòng)態(tài)的增加或退出某組播組。
三、單播、廣播、組播的編程實(shí)例。
(1)單播實(shí)例:(一個(gè)echoserver,能夠同一時(shí)候和多個(gè)用戶通信)
head.h
<span style="font-size:12px;">#ifndef _HEAD_H_ #define _HEAD_H_#include<stdio.h> #include<string.h> #include<strings.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<netinet/in.h> #include<error.h> #include<errno.h> #include<unistd.h> //fork #include<sys/wait.h>#define SER_PORT 50004 #define SER_IP "192.168.192.128" #define CLIENT_PORT 50000 #define CLIENT_IP "192.168.192.128"#define BUFF_SIZE 100 #define SIZE 20typedef struct _USER {char name[SIZE];char passwd[SIZE]; }usr; #define sys_err(_msg) error(EXIT_FAILURE,errno,_msg) /*errno是個(gè)全局變量,調(diào)用之后,能夠在錯(cuò)誤發(fā)生的情況下,也能輸出——msg信息 *作為調(diào)試用 * */ #endif </span>
server.c
<span style="font-size:12px;">#include "head.h" int socket_init() {int sockfd;struct sockaddr_in sockaddr;if((( sockfd=socket(AF_INET,SOCK_STREAM,0))==-1))sys_err("socket");bzero(&sockaddr,sizeof(sockaddr));sockaddr.sin_family=AF_INET;sockaddr.sin_port=htons(SER_PORT);sockaddr.sin_addr.s_addr=inet_addr("127.0.0.1");printf("%d=====\n",sockfd);if((bind(sockfd,(struct sockaddr*)&sockaddr,sizeof(sockaddr)))==-1)sys_err("bind");listen(sockfd,5); //要懂得監(jiān)聽的作用,事實(shí)上就是建立一個(gè)緩沖隊(duì)列,讓創(chuàng)建的隊(duì)列最多能夠同意五個(gè)套接字進(jìn)入return sockfd; }int do_echo(int connectfd) {char sbuf[BUFF_SIZE];char rbuf[BUFF_SIZE];int n;printf("int the server ==========\n");while(1){printf("===============in the do_echo\n");bzero(rbuf,BUFF_SIZE);if((n=recv(connectfd,rbuf,BUFF_SIZE,0))==-1)sys_err("recv");if(n==0) //假設(shè)接受為0,代表client已經(jīng)斷線,返回-1return -1;printf("server:rbuf==%s\n",rbuf);sprintf(sbuf,"%s %s",rbuf,"---------echo");send(connectfd,sbuf,strlen(sbuf),0);}return ; } int main(int argc,const char * argv[]) {//步驟:/**1 創(chuàng)建套接字socket();*2 與IP地址綁定bind();*3監(jiān)聽 listen();*4假設(shè)有鏈接,接受鏈接,進(jìn)行三次握手accept();*5與client進(jìn)行數(shù)據(jù)的傳輸read(),send();*6關(guān)閉套接字close(sockfd);* *注意:要掌握熟練掌握各個(gè)接口的調(diào)用* 為了實(shí)現(xiàn)多client和服務(wù)器的交互,該怎么做* */int sockfd;//具有基本屬性的套接字描寫敘述符int connectfd;//進(jìn)行三次握手之后的套接字描寫敘述符sockfd=socket_init();//listen(sockfd,5); //要懂得監(jiān)聽的作用,事實(shí)上就是建立一個(gè)緩沖隊(duì)列,讓創(chuàng)建的將要//連接的套接字描寫敘述符進(jìn)隊(duì)和出隊(duì) /**** The accept() system call is used with connection-based socket types* (SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection request on the* queue of pending connections for the listening socket, sockfd, creates a new*** */pid_t pid;signal(SIGCHLD,SIG_IGN);while(1){connectfd=accept(sockfd,NULL,NULL); //一個(gè)服務(wù)器能夠和多個(gè)client進(jìn)程多次握手連接。 切記,connect()函數(shù)在UDP協(xié)議中也能夠用,不是TCP的專用if(connectfd == -1)sys_err("accept");if(-1==(pid=fork())){perror("fork");}else if(pid==0){printf("do_echo===%d\n", do_echo(connectfd));close(connectfd); //將子進(jìn)程從父進(jìn)程拷貝到的套接字資源,關(guān)閉了close(sockfd);}} close(connectfd);//父進(jìn)程關(guān)閉自己的套接字close(sockfd);return 0;}</span><span style="font-size:14px;"> </span>
(2)廣播實(shí)例:
sender.c ?:
<span style="font-size:14px;">#include"head.h" int main(int argc,const char * argv[]) {int sockfd;struct sockaddr_in sockaddr;char rbuf[BUFF_SIZE];if(-1==(sockfd=socket(AF_INET,SOCK_DGRAM,0))) //因?yàn)門CP僅僅支持一對(duì)一通信,UDP能夠一對(duì)一,一對(duì)多,多對(duì)一,多對(duì)多。因?yàn)檫@個(gè)廣播。是多對(duì)多。所以僅僅能是SOCK_DGRAMperror("socket");bzero(&sockaddr,sizeof(sockaddr));sockaddr.sin_family=AF_INET;sockaddr.sin_port=htons(BRAOD_PORT); //#define BRAOD_PORT 50001sockaddr.sin_addr.s_addr=inet_addr(BRAOD_IP);//#define BRAOD_IP "192.168.1.255"if(-1==bind(sockfd,(struct sockaddr *)&sockaddr,sizeof(sockaddr)))perror("bind");while(1){bzero(&rbuf,sizeof(rbuf));recvfrom(sockfd,rbuf,BUFF_SIZE,0,(struct sockaddr*)&sockaddr,sizeof(sockaddr));printf("--------%s-------\n",rbuf);}close(sockfd);return 0; }</span>
(3)組播實(shí)例:
sender.c :
<span style="font-size:14px;">#include"head.h" int main(int argc ,const char * argv[]) {/**創(chuàng)建組播發(fā)送方的步驟:*創(chuàng)建套接字*設(shè)置組播地址(可選)*發(fā)送數(shù)據(jù)*關(guān)閉套接字* */int sockfd;struct sockaddr_in multiaddr;char sbuf[BUFF_SIZE]="hello,xiaowang....\n";int n;if(-1==(sockfd=socket(AF_INET,SOCK_DGRAM,0)))perror("socket");bzero(&multiaddr,sizeof(multiaddr));multiaddr.sin_family=AF_INET;multiaddr.sin_port=htons(MULTI_PORT); //#define MULTI_PORT 50002 僅僅要是用戶自己定義端口就可以multiaddr.sin_addr.s_addr=inet_addr(MULTI_IP);</span><span style="font-size:14px;"> //#define MULTI_IP "224.4.4.4" D類地址是組播地址224.0.0.1---239.255.255.254while(1){sleep(1);if(-1==(n=sendto(sockfd,sbuf,strlen(sbuf),0,(struct sockaddr*)&multiaddr,sizeof(multiaddr))))perror("sendto");printf("in the sending..........\n");} return 0; }</span>
recevier.c :
<span style="font-size:14px;">#include"head.h" int main(int argc,const char * argv[]) {int sockfd;int n;char rbuf[BUFF_SIZE];struct sockaddr_in groupaddr;//創(chuàng)建套接字if(-1==(sockfd=socket(AF_INET,SOCK_DGRAM,0)))perror("socket");//增加組播struct ip_mreqn multiaddr; //這些在Man 2 setsockopt 時(shí)在signal的有關(guān)描寫敘述中能夠查到的multiaddr.imr_multiaddr.s_addr=inet_addr(MULTI_IP);multiaddr.imr_address.s_addr=inet_addr(LOCAL_IP);multiaddr.imr_ifindex=0;//設(shè)置套接字同意發(fā)送組播信息的屬性if(-1==setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&multiaddr,sizeof(multiaddr)))perror("setsockopt");//綁定組播地址bzero(&groupaddr,sizeof(groupaddr));groupaddr.sin_family=AF_INET;groupaddr.sin_port=htons(MULTI_PORT);groupaddr.sin_addr.s_addr=inet_addr(MULTI_IP);bind(sockfd,(struct sockaddr*)&groupaddr,sizeof(groupaddr));int t;while(1){// bzero(&rbuf,sizeof(rbuf));t=sizeof(groupaddr);if(-1==(n=recvfrom(sockfd,rbuf,BUFF_SIZE,0,(struct sockaddr*)&groupaddr,&t)))perror("recvfrom");sleep(1); printf("%s-----------\n",rbuf);}return 0; } </span>
?
參考文獻(xiàn):http://www.xici.net/d79537500.htm
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 未經(jīng)同意,禁止轉(zhuǎn)載
轉(zhuǎn)載于:https://www.cnblogs.com/blfshiye/p/4357492.html
總結(jié)
以上是生活随笔為你收集整理的网络通信:单播、广播、组播的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA之关于This的用法
- 下一篇: IOS atomic与nonatomic