首页 > 其他分享 >广播数据包-大声说「Hello,World」

广播数据包-大声说「Hello,World」

时间:2022-10-29 23:02:41浏览次数:49  
标签:addr BROADCAST their 广播 World include 数据包 Hello



  • 英文小册原文地址:​​beej.us/guide/bgnet…​​
  • 作者:Beej
  • 中文翻译地址:​​www.chanmufeng.com/posts/netwo…​​

到目前为止,我们已经讨论了怎么从一台主机发送数据到另一台主机。但是,如果有这种可能,你肯定想同时把数据发送给多台主机。

用​​UDP​​​(只能用​​UDP​​​,​​TCP​​不行)和标准的IPv4,可以通过一种叫做广播(broadcasting)的机制来实现。IPv6不支持广播,你得用一种更高级的技术——多播(multicasting)来实现。这个技术我们这次不会讲,毕竟我们现在还停留在IPv4的32位阶段呢,就不异想天开了。

Wait!你别溜走,自己偷摸开始广播,我还没开始介绍呢。你必须设置套接字选项​​SO_BROADCAST​​,然后才能在网络上发送广播数据包,这就好比是在导弹发射开关上盖的一个小塑料罩,你的一根指头就可以控制所有!

但是,说真的,使用广播数据包有一个危险,因为每个收到广播包的系统都要拨开一层层像洋葱皮一样的封装,直到系统知道这个资料是要发送到哪个 port 为止,然后系统会开始处理这个数据或者将其丢弃。

无论怎样,接收广播数据包的每台机器都要做很多工作,而且因为它们都在本地网络上,所以可能会有很多机器做很多不必要的工作。

现在,有很多方法可以解决这个问题。。。

等一下,真的有很多方法吗?

那是什么表情阿?让我告诉你吧,发送广播包的方式有很多,所以重点就是:你该如何指定广播数据的目地地址?

有两种常用的方法:

  1. 将数据发送到指定子网的广播地址,就是把子网( subnet's network)的主机( host)部分全部填​​1​​​。例如,我的网络是​​192.168.1.0​​​,我的子网掩码是​​255.255.255.0​​​,所以地址的最后一个字节是我的主机号(因为根据网络掩码,前3个字节是网络号),所以我的广播地址是​​192.168.1.255​​​。在Unix下,​​ifconfig​​会告诉你这些信息的。你可以将这种类型的广播数据包发送到远程网络和本地网络,但你会面临数据包被目标路由器丢弃的风险。(如果他们不放弃它,那这些广播数据可能会淹没他们的局域网。)
  2. 将数据发送到“全局(global)”广播地址。这是​​255.255.255.255​​,即INADDR_BROADCAST。许多机器会自动将其与您的网络号码「按位与」,以将其转换为网络广播地址,但有些机器却不会。具有讽刺意味的是,路由器不会把这种类型的广播数据包从你的本地网络转发出去。

所以如果你想要将数据送到广播地址,但是并没有设置 ​​SO_BROADCAST​​ socket 选项时会怎么样呢?好,我们用之前的 ​​talker 与 listener​​ 来炒个冷饭,然后看看会发生什么事情。

$ talker 192.168.1.2 foo
sent 3 bytes to 192.168.1.2
$ talker 192.168.1.255 foo
sendto: Permission denied
$ talker 255.255.255.255 foo
sendto: Permission denied

如你所见,数据发送得并不顺利......因为我们没有设置​​SO_BROADCAST​​​这个socket选项,设置一下,然后你就可以用​​sendto()​​将数据发送到任何你想发送的地方去了。

事实上,这是​​UDP​​​应用程序可以广播和不能广播的唯一区别。因此,我们改造一下之前的​​talker​​​程序,添加一个设置​​SO_BROADCAST​​套接字选项的部分。代码如下:

/*
** broadcaster.c -- a datagram "client" like talker.c, except
** this one can broadcast
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define SERVERPORT 4950 // the port users will be connecting to

int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in their_addr; // connector's address information
struct hostent *he;
int numbytes;
int broadcast = 1;
//char broadcast = '1'; // if that doesn't work, try this

if (argc != 3) {
fprintf(stderr,"usage: broadcaster hostname message\n");
exit(1);
}

if ((he=gethostbyname(argv[1])) == NULL) { // get the host info
perror("gethostbyname");
exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}

// this call is what allows broadcast packets to be sent:
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast,
sizeof broadcast) == -1) {
perror("setsockopt (SO_BROADCAST)");
exit(1);
}

their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(SERVERPORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);

if ((numbytes=sendto(sockfd, argv[2], strlen(argv[2]), 0,
(struct sockaddr *)&their_addr, sizeof their_addr)) == -1) {
perror("sendto");
exit(1);
}

printf("sent %d bytes to %s\n", numbytes,
inet_ntoa(their_addr.sin_addr));

close(sockfd);

return 0;
}

标签:addr,BROADCAST,their,广播,World,include,数据包,Hello
From: https://blog.51cto.com/u_13887950/5806588

相关文章

  • Python—运行Hello程序
          运行Python程序有两种方式:交互式和文件式。交互式是指Python解释器即时响应用户输入的每条代码,给出输入结果。文件式,也称为批量式,指用户将Python程序写入一个......
  • 请求www.baidu.com时数据包转发过程
    文章目录​​一、同一个局域网中不同主机的互联​​​​二、跨网段请求百度的服务器​​​​三、百度的响应包如何再打回到你的机器?​​一、同一个局域网中不同主机的互联先......
  • react实战笔记21:HelloWorld-第一个程序-react创建
     ......
  • golang学习之路1-环境安装及Helloword
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档@目录Golang学习之路前言一、安装环境1.Golang安装2.GoLand安装二、第一个go程序HelloWord三、go命令......
  • php学习笔记二:第一个php程序 hello world!
    第一个php程序helloworld!前提条件:已经安装xampp和phpstorm xampp安装到了D:\xampp1打开phpstorm2新建项目保存项目到 D:\WorkTest\Php3添加index.php文件4......
  • Java的第一个程序“Hello word!”
     前提条件:新建文件夹,存放代码(code)新建一个Java文档,将.text改成.Java编写程序publicclassHello{publicstaticvoidmain(Sting【】args{System.out.print(“......
  • 【CF1299D】Around the World(线性基)
    题意:给定一张\(n\)个点\(m\)条边的无向连通图,边带权,保证不存在一个长度\(>3\)的简单环经过了\(1\)号点。请求出有多少种方案删除若干条与\(1\)号点相连的边,使得......
  • 从新开始学JAVA - Hello World与Java运行机制
    代码publicclassHello{publicstaticvoidmain(String[]args){System.out.print("Hello,World!");}}注意类的名字大些分号Java是大小写......
  • 3.Hello Spring(第一个Spring项目)
    3.HelloSpring报错cannotresolvemethodgetBean(java.lang.String)添加注解@AutowiredpublicclassMyTest{@Autowiredpublicstaticvoidmain(String[]args)......
  • 《HelloGitHub》第 79 期
    兴趣是最好的老师,HelloGitHub让你对编程感兴趣!简介HelloGitHub分享GitHub上有趣、入门级的开源项目。https://github.com/521xueweihan/HelloGitHub这里有实......