轉(zhuǎn)載 http://blog.csdn.net/tennysonsky/article/details/45563851#
概述
在生活中廣播無處不在异吻,像平時(shí)在大街上賣物品的商人喜庞,在進(jìn)行推廣產(chǎn)品的時(shí)候往往都是使用一個(gè)喇叭來進(jìn)行吆喝:“十塊錢買不了吃虧诀浪,十塊錢買不了上當(dāng)延都,走過路過千萬不要錯(cuò)過”,這就是廣播窄潭。
那么在網(wǎng)絡(luò)中的廣播又是什么樣子的呢酵颁?
網(wǎng)絡(luò)上的廣播指:由一臺主機(jī)向該主機(jī)所在子網(wǎng)內(nèi)(同一個(gè)局域網(wǎng))的所有主機(jī)發(fā)送數(shù)據(jù)的方式。如下圖的 1 號主機(jī)廣播給 2躏惋、3、4距误、5 號主機(jī)發(fā)送數(shù)據(jù):
實(shí)現(xiàn)廣播扁位,離不開廣播地址准潭,同一個(gè)子網(wǎng)(局域網(wǎng))的所有主機(jī)網(wǎng)卡都會(huì)接收所在網(wǎng)段廣播地址的數(shù)據(jù)包域仇。廣播地址應(yīng)用于局域網(wǎng)內(nèi)的所有主機(jī)。
廣播地址(Broadcast Address)是專門用于同時(shí)向網(wǎng)絡(luò)中(通常指同一子網(wǎng))所有工作站進(jìn)行發(fā)送的一個(gè)地址暇务。
廣播地址主要分為兩類
1)受限廣播
路由器從來不會(huì)轉(zhuǎn)發(fā)受限廣播的數(shù)據(jù)包怔软,但同一個(gè)子網(wǎng)的所有主機(jī)都會(huì)接收到受限廣播的數(shù)據(jù)包择镇。
IP 地址的網(wǎng)絡(luò)字段和主機(jī)字段全為 1 就是受限廣播地址255.255.255.255挡逼。
2)直接廣播(也叫定向廣播)
直接廣播可以被路由轉(zhuǎn)發(fā)腻豌,發(fā)送到目標(biāo)網(wǎng)絡(luò)的所有主機(jī),如:ip地址為 192.168.2.1的主機(jī)也可以發(fā)送廣播到 192.168.1.0 這個(gè)網(wǎng)絡(luò)饲梭。當(dāng)然不是所有的路由器,通常路由器是默認(rèn)阻止直接廣播的(可以設(shè)置不阻止)憔涉。
IP 地址的網(wǎng)絡(luò)字段定義這個(gè)網(wǎng)絡(luò),主機(jī)字段通常全為 1穿扳,如192.168.10.0/24 的直接廣播(定向廣播)地址為:192.168.10.255。
廣播地址的更詳細(xì)介紹矛物,請看《廣播地址介紹》。
廣播特點(diǎn)
對于一個(gè)帶網(wǎng)卡設(shè)備的主機(jī)履羞,它能接收到哪些網(wǎng)絡(luò)數(shù)據(jù)包呢?
1)網(wǎng)卡會(huì)接收目的 ip 和它的 ip 地址相同的數(shù)據(jù)包(至于能不能到應(yīng)用層我們暫時(shí)不管忆首,至于MAC地址如何確定我們暫時(shí)也不管)被环,這個(gè)就是單播傳輸數(shù)據(jù)糙及。
2)網(wǎng)卡會(huì)接收到目的 ip 為廣播地址數(shù)據(jù)包筛欢,這個(gè)廣播地址的 MAC 地址為:ff:ff:ff:ff:ff:ff 。
3)如果這個(gè)主機(jī)加入了多播組版姑,它也會(huì)接收該多播組地址的數(shù)據(jù)包,詳情請看《多播》剥险。
廣播只能用 UDP 或原始IP實(shí)現(xiàn),不能用 TCP。
UDP 廣播特點(diǎn)如下:
處于同一子網(wǎng)的所有主機(jī)都必須處理數(shù)據(jù)匈庭。
UDP 數(shù)據(jù)包會(huì)沿協(xié)議棧向上一直到 UDP 層,因?yàn)榈?UDP 層阱持,端口不匹配的話,數(shù)據(jù)才會(huì)丟棄衷咽,如下圖,所以镶骗,運(yùn)行音視頻等較高速率工作的應(yīng)用躲雅,會(huì)帶來較大的負(fù)擔(dān)鼎姊。
廣播示例使用
默認(rèn)的情況下相赁,不允許發(fā)送廣播數(shù)據(jù)包,需要修改套接口選項(xiàng):
*int setsockopt( int sockfd, int level, int optname,const void optval, socklen_t optlen);
功能:
設(shè)置套接字選項(xiàng)
參數(shù):
sockfd:套接字
其它參數(shù)說明如下:
注意:optval的值應(yīng)該這樣填唤衫,定義一個(gè)賦值為 1 的整型變量,int opt=1, 然后把這個(gè)變量的地址放這個(gè)位置佳励,如:&opt
返回值:
成功執(zhí)行返回0,否則返回-1
使用例子如下:
[cpp] view plain copy
//設(shè)置該套接字為廣播類型
int opt=1;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
下面我們寫一個(gè) UDP 廣播發(fā)送數(shù)據(jù)包例子赃承,目的端口指定為 8000璃吧,目的 IP 為受限廣播地址:255.255.255.255楣导,那樣畜挨,同一個(gè)局域網(wǎng)的所有主機(jī)網(wǎng)卡都會(huì)收到這個(gè)數(shù)據(jù)噩凹,但是巴元,只有端口為 8000 的網(wǎng)絡(luò)應(yīng)用程序才會(huì)收到這個(gè)數(shù)據(jù)包:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
unsigned short port = 8000; // 端口
char *server_ip = "255.255.255.255"; // 受限廣播地址
int sockfd;
sockfd = socket(AF_INET, SOCK_DGRAM, 0); //創(chuàng)建UDP套接字
if(sockfd < 0)
{
perror("socket");
exit(-1);
}
struct sockaddr_in dest_addr;
bzero(&dest_addr, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
inet_pton(AF_INET, server_ip, &dest_addr.sin_addr);
printf("send data to UDP server %s:%d!\n", server_ip, port);
//設(shè)置該套接字為廣播類型驮宴,這個(gè)很重要
int opt=1;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
char send_buf[512] = "this is a broadcast data";
sendto(sockfd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));//發(fā)送數(shù)據(jù)
close(sockfd);
return 0;
}
編譯運(yùn)行如下: