用udp實現廣播通訊
作者:lycclsltt
原文:https://blog.csdn.net/aspnet_lyc/article/details/34444111
特點:
1.資料傳輸不用建立連線,所以不可靠(符合udp協議的特點)
2.資料的傳送是面向整個子網的,任何一臺在子網內的計算機都可以接收到相同的資料;
3.廣播用於udp和原始IP,不能用於TCP
用途:
1.定位本地子網內的主機
前提是已知該主機位於本地子網,但是不知到他的單播地址。例如通過廣播向所有子網內的主機的某埠傳送資料報,如果主機有程序在該埠等待接收資料並回射資料,那麼在recvfrom中會得到該主機的單播地址
2.減少分組流通
例如,多個客戶主機與一個伺服器主機通訊的區域網中,廣播的方式會盡量減少分組流通。
廣播地址:
廣播地址是專門用於同時向網路中所有工作站進行傳送的一個地址。在使用TCP/IP 協議的網路中,主機號為全1的IP地址為廣播地址。例如,對於 :192.168.199.0(掩碼:255.255.255.0)網段,其廣播地址為192.168.199.255 (255 即為2進位制的11111111 ),當發出一個目的地址為192.168.199.255的分組時,它將被分發給該網段上的所有計算機。
1.直接廣播地址
指Host部分全為1的廣播地址。如:192.168.199.255。當某機器發出目的地址為直接廣播(如:192.168.199.255)時,路由器通過查詢路由表可以轉發,直到該網段。
2.受限廣播地址
也稱本地廣播地址,它不被路由傳送,但會被送到相同物理網路段上的所有主機,IP地址的網路號和主機號 全為1就是地址255.255.255.255,當某機器發出目的地址為本地廣播時,路由器不會轉發該包。所以該包只能限制在本網段
例項:
server.cpp #include <iostream> #include <strings.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> using namespace std; int main() { int sockfd; struct sockaddr_in saddr; int r; char recvline[1025]; struct sockaddr_in presaddr; socklen_t len; sockfd = socket(AF_INET, SOCK_DGRAM, 0); bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(9999); bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr)); while (1) { r = recvfrom(sockfd, recvline, sizeof(recvline), 0 , (struct sockaddr*)&presaddr, &len); if (r <= 0) { perror(""); exit(-1); } recvline[r] = 0; cout <<"recvfrom "<< inet_ntoa(presaddr.sin_addr) <<" " << recvline << endl; } return 0; }
client.cpp
#include <iostream>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
int sockfd;
struct sockaddr_in des_addr;
int r;
char sendline[1024] = {"Hello"};
const int on = 1;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); //設定套接字選項
bzero(&des_addr, sizeof(des_addr));
des_addr.sin_family = AF_INET;
des_addr.sin_addr.s_addr = inet_addr("192.168.199.255"); //廣播地址
des_addr.sin_port = htons(9999);
r = sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr*)&des_addr, sizeof(des_addr));
if (r <= 0)
{
perror("");
exit(-1);
}
cout << "finish" << endl;
return 0;
}
問題:
使用廣播的問題在於它增加了對廣播資料不感興趣主機的處理負荷。拿一個使用UDP廣播應用作為例子。如果網內有50個主機,但僅有20個參與該應用,每次這20個主機中的一個傳送UDP廣播資料時,其餘30個主機不得不處理這些廣播資料報。一直到UDP層,收到的UDP廣播資料報才會被丟棄。這30個主機丟棄UDP廣播資料報是因為這些主機沒有使用這個目的埠。