[pid 477] sendto(124, "k\202\2\0210\202\2\r\240\3\2\1\5\241\3\2\1\v\243\5\33\3TDH\244\0220\20\240\3\2"..., 533, 0, {sa_family=AF_INET6, sin6_port=htons(38790), inet_pton(AF_INET6, "::ffff:172.17.0.3", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 533
其对应的逻辑是这样的:运用 ipv6 绑定在 0.0.0.0 和 6088 端口,调用 getsockname 获取以后 socket 绑定的端口信息,数据传输进程运用的是 recvfrom 和 sendto 。
比照上去,两者的不同有几点:
后者运用的是 ipv6,而前者是 ipv4
后者运用 recvfrom 和 sendto 传输数据,而前者是 sendmsg 和 recvmsg
前者有调用 setsockopt 设置 IP_PKTINFO 的值,然后者没有
由于是在传输数据的时分出错的,因此第一个疑点是 sendmsg 和 sendto 的某些区别招致选择源地址有不同,经过 man sendto 可以知道 sendmsg 包含了更多的控制信息在 msghdr 。一个合理的猜测是 msghdr 中包含了内核选择源地址的信息!
经过查找,发现 IP_PKTINFO 这个选项就是让内核在 socket 中保存 IP 报文的信息,当然也包括了报文的源地址和目的地址。 IP_PKTINFO 和 msghdr 的关系可以在这个 stackoverflow 中找到:https://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket。
而 man 7 ip 文档中也阐明了 IP_PKTINFO 是怎样控制源地址选择的:
IP_PKTINFO (since Linux 2.2)
Pass an IP_PKTINFO ancillary message that contains a pktinfo structure that supplies some information about the incoming packet. This only works for datagram ori‐
ented sockets. The argument is a flag that tells the socket whether the IP_PKTINFO message should be passed or not. The message itself can only be sent/retrieved as
control message with a packet using recvmsg(2) or sendmsg(2).
struct in_pktinfo {
unsigned int ipi_ifindex; /* Interface index */
struct in_addr ipi_spec_dst; /* Local address */
struct in_addr ipi_addr; /* Header Destination
address */
};
ipi_ifindex is the unique index of the interface the packet was received on. ipi_spec_dst is the local address of the packet and ipi_addr is the destination address
(责任编辑:admin)