首页 > 代码库 > 用udp实现广播通信

用udp实现广播通信

特点:

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广播数据报是因为这些主机没有使用这个目的端口。