我对网络编程非常陌生,我已经尝试了很长一段时间都在想这件事。在通过互联网浏览了大量的资源之后,我得出了以下的结论,并对此感到困惑。
结论1:当我们讨论将套接字创建为:
s = socket(AF_INET, SOCK_RAW, 0);我们基本上是在尝试创建一个原始套接字。使用这样创建的原始套接字,可以绕过OSI堆栈中的TCP/UDP层。这意味着,当应用程序通过这个套接字接收到数据包时,应用程序将有包含网络层(第三层)报头的包包装第二层报头,包装实际数据。因此,应用程序可以自由地处理这个包,超过第三层,在任何它想要的。
类似地,当通过这个套接字发送数据包时,应用程序也可以自由地处理数据包的创建,直到第4层,然后将其传递到第3层,从第三层开始,内核上的点将处理这些事情。
结论2:当我们讨论将套接字创建为:
s = socket(AF_PACKET, SOCK_RAW, 0);我们再次尝试创建一个原始套接字。使用这样创建的原始套接字,您将能够完全绕过OSI的所有层。一个纯粹的原始包将提供给用户土地应用程序,它可以自由地对该包做它想做的任何事情。通过这样一个套接字接收的数据包将完整地拥有所有的标头,并且应用程序还可以访问所有这些标头。
类似地,在通过这样一个套接字发送数据时,用户应用程序必须处理与创建数据包和用每个层的头部包装实际数据有关的所有内容,然后才能将其实际放置到要传输的物理介质上。
结论3:当我们讨论创建套接字时,是:
s = socket(AF_PACKET, SOCK_DGRAM, 0);我们再次尝试创建一个原始套接字。使用这样创建的原始套接字,您将能够绕过OSI堆栈中的数据链路层(第2层)。也就是说,当用户陆地应用程序接收到这样一个套接字上的数据包时,数据链路层报头被从数据包中移除。
类似地,在通过此套接字发送数据包时,根据sockaddr_ll目标地址中的信息,向数据包添加合适的数据链路层报头。
下面是我的疑问/困惑之处:
我刚才所提及的一些资源,旨在了解上述各点:
https://docs.freebsd.org/44doc/psd/21.ipc/paper.pdf
PACKET/
http://opensourceforu.com/2015/03/a-guide-to-using-raw-sockets/
RAW' option in 'socket' system call
http://stevendanna.github.io/blog/2013/06/23/a-short-sock-raw-adventure/
发布于 2022-04-26 18:55:52
你更接近他们的真实解释了。我有件事要告诉你我觉得你错过了什么或者错了什么。
首先,对于s = socket(AF_INET, SOCK_RAW, 0);,当通过这样的套接字接收数据包时,它将始终包含一个IP报头。如果未启用IP_HDRINCL,则为了发送,数据包必须包含IP报头,则TCP/IP堆栈将不会为您生成此消息。所有其他上层可以通过这个插座接收。
其次,s = socket(AF_PACKET, SOCK_RAW, 0);
这是Linux系统中一种特殊的原始套接字,称为数据包套接字.这种类型的套接字允许在OSI第2层发送和接收数据包,这就是为什么用于这种套接字的API被称为链接层API。任何协议都可以通过这个套接字在物理层的顶部实现。有趣的是,我们还可以用这个套接字与数据包的预告片进行交互,尽管我们并不经常需要。
第三,如果是s = socket(AF_PACKET, SOCK_DGRAM, 0);,你的结论是正确的。在这种类型的数据包套接字中,不需要考虑以太网报头。这比以前的类型要高一些。
因此,我们可以说,这些类型的套接字的主要区别在于它们访问的可能性。概括地说:
| Layer 3 header | Layer 4 header | Payload |
| Layer 2 header | Layer 3 header | Layer 4 header | Payload | Layer 2 trailer |
https://stackoverflow.com/questions/49309029
复制相似问题