1. 程式人生 > >用udp實現廣播通訊

用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廣播資料報是因為這些主機沒有使用這個目的埠。