这很好用:
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
connect(4, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("1.1.1.1")}, 16) = 0
我们可以观察到本地和远程的正确绑定:
$ sudo lsof -Pni :4444
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
udpdup 2815 nhed 4u IPv4 126724 0t0 UDP 10.0.2.15:4444->1.1.1.1:*
但是先连接,绑定时出错,为什么?
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
connect(4, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("1.1.1.1")}, 16) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EINVAL (Invalid argument)
我为什么关心你问的问题?
我认为接收到的数据包与 5 元素元组(proto、loc addr、loc port、rem addr、rem port)进行匹配。其中 5 个中的一些可以是 ANY(通配符),在
0
中以数字形式表示为 0.0.0.0
或 struct sockaddr_in
,通常用 netstat
、lsof
等表示。上面的 lsof
输出显示 4 /5 指定元素,远程端口保留为通配符)
我不记得是否应该存在多个套接字,其中一些套接字具有通配符对等地址,而其他套接字可能是显式的,根据最佳匹配将流量发送到正确的端口。
我想尝试并检查当一个应用程序在未指定发送者地址的情况下绑定端口时,另一个应用程序可以连接并绑定对等方,以形成更完整的元组。 [注意第一个应用程序没有指定
SO_REUSEADDR
]
附注有足够积分的人可以创建一个
udp-connect
标签吗? (甚至还有 udp 绑定)
connect(2)
隐式绑定您的本地端口,因此后续显式 bind(2)
失败。
您可以将多个套接字绑定到同一个本地端口,但第一个套接字之后的所有绑定都必须更加具体。比如说,第一个套接字绑定到
INADDR_ANY
,其他套接字绑定到现有网络接口的特定地址。请注意,all 套接字必须设置为 SO_REUSEADDR
。
然后是多播,它允许您创建完全重复的套接字绑定,但仅限于特定类别的地址,并且您必须做更多的工作来设置它。
在我看来,您也将其与 TCP 监听与连接套接字混淆了。
connect(2)
还根据到目的地的路由固定套接字本地地址。