对于网络通讯,耳熟能详的莫过于TCP、UDP,二者皆需要ip和port。对于一般开发人员,找到一个“能用”的库就可以了,因为流式通讯,会有粘包问题,那就需要再加一个库,解决粘包问题,这样一个基本的通讯框架就OK了。很多情况下,我们并没有了解网络通讯内部的结构,对于网络7层模型也是一知半解,这些都很值得探索。考虑一种情况:当我们的linux上位机需要和嵌入式设备进行网络通讯,选择哪种网络协议比较好呢?它是位于哪种通讯层次呢?如果上位机要与多台嵌入式设备通讯,又该如何处理呢?接下来了解今天的的主角——raw socket。
raw socket用于接收原始数据包。这意味着在Ethernet层接收到的数据包将直接传递到raw socke。准确地说,原始套接字绕过正常的 TCP/IP 处理并将数据包发送到特定的用户应用程序(参见图 1)。
其他套接字(例如stream sockets 和data gram sockets)从传输层接收数据,该数据不包含headers ,仅包含payload。这意味着没有关于源IP地址和MAC地址的信息。如果运行在同一台机器或不同机器上的应用程序正在通信,那么它们只是交换数据。
raw socket的用途完全不同。原始套接字允许应用程序直接访问较低级别的协议,这意味着原始套接字接收未提取的数据包(参见图 2)。与流和数据报套接字的情况不同,无需向原始套接字提供端口和 IP 地址。
当应用程序将数据发送到网络时,数据会由各个网络层进行处理。在发送数据之前,它被包装在网络层的各种headers中。数据的包装形式包含源地址和目标地址等所有信息,称为网络数据包(参见图 3)。根据以太网协议,有多种类型的网络数据包,如Internet协议数据包、Xerox PUP数据包、以太网环回数据包等。在Linux中,我们可以在if_ether.h头文件中看到所有协议(见图4 )。
通用网络数据包
互联网协议网络数据包
ieee 802.3
当我们连接到互联网时,我们接收网络数据包,我们的机器提取所有网络层标头并将数据发送到特定应用程序。例如,当我们在浏览器中输入www.baidu.com时,我们会收到BaiDu发送的数据包,我们的机器会提取网络层的所有headers并将数据提供给我们的浏览器。
默认情况下,机器会接收与本机具有相同目的地址的数据包,这种模式称为非混杂模式。但如果我们想接收所有数据包,我们必须切换到混杂模式。我们可以借助ioctl 进入混杂模式。
如果我们对不同网络层的标头的内容或结构感兴趣,我们可以借助数据包嗅探器来访问它们。有多种适用于 Linux 的数据包嗅探器,例如 Wireshark。有一个名为tcpdump 的命令行嗅探器,它也是一个非常好的数据包嗅探器。如果我们想制作自己的数据包嗅探器,如果我们了解 C 语言和网络基础知识,就可以轻松完成。下次将展示raw socket具体通讯例子,并且解析数据帧。
欢迎大家关注公众号: