因为要使用 python 底层发包模块,也就是 raw socket 发包模式,所以在此深入了解一下 python socket 通信。
涉及到的函数:
import socket
socket()
setsockopt()
sendto()
recvfrom()
因为使用的是原始套接字,所以我们不使用bind/connect函数,参照《unix 网络编程》
bind 函数仅仅设置本地地址。就输出而言,调用bind函数设置的是将用于从这个原始套接字发送的所有数据报的源IP地址。如果不调用bind,内核就吧源IP地址设置为外出接口的主IP地址。
connect函数仅仅设置外地地址,同样因为原始套接字不存在端口号的概念。就输出而言,调用connect之后我们可以把sendto调用改为write或者send调用,因为目的IP地址已经指定了。
顺便说一句,connect函数也是三次握手的发生过程,参见链接
套接字参数
官网介绍:
socket.socket([family[, type[, proto]]])
参数说明:
family:协议簇/地址簇。
最常用的就是 socket.AF_INET 了,TCP/UDP 通信均属于此类型。
PS:有时我们看到的协议常量名为 AF_xxx,有时又是 PF_xxx,可以理解为 address family 和 protocol family,实际使用中是没有区别的。一般在区分协议的时候习惯使用 PF ,而在区分地址的时候习惯使用AF。可以参照这个链接的解释:
Yes. AF_foo means address family foo, and PF_foo means protocol family foo. In Linux, they are always been the same values, I believe.
Traditionally, the PF_foo constants were used for socket(), but AF_foo in the struct sockaddr structure.
According to man 2 socket, even the (historical) BSD 4.x man page states that "The protocol family generally is the same as the address family", and subsequent standards use AF_* everywhere.
Thus, today, there really should be no difference between AF_foo and PF_foo.
除此之外常用的还有 AF_UNIX/AF_LOCAL ,代表UNIX域协议,属于IPC(进程间通信)的一种方式;AF_INET6 ,IPv6 通信。
socket.AF_UNIX