linux下tcp端口复用(bind_conflict)

来源:互联网 发布:赵文卓甄子丹事件 知乎 编辑:程序博客网 时间:2024/06/03 09:25
这个函数中在tcp_init中注册,当调用tcp接口inet_csk_get_port时,发现端口已经补占用,那么调用该函数负责处理冲突,也就是说一旦查找到的inet_bind_bucket和当前的sock有冲突,那么就有必要去化解一下僵局,这也表明事情不是不可化解的,linux规定在以下的情况下可以重用端口:


1.绑定不同网络接口的可以使用同一个端口;


2.每一个设置了地址重用的并且都不处于listen状态的所有的套接字可以使用一个端口,这意味着它们都是主动外出的套接字,目的由它们自己掌握;


3.即便在1和2都不满足的情况下,使用不同源地址的服务器套接字也可以使用同一个端口。对于一般的tcp协议,该处理冲突的回调函数就是inet_csk_bind_conflict:


int inet_csk_bind_conflict(const struct sock *sk, const struct inet_bind_bucket *tb)


{


const __be32 sk_rcv_saddr = inet_rcv_saddr(sk);


struct sock *sk2;


struct hlist_node *node;


int reuse = sk->sk_reuse;


sk_for_each_bound(sk2, node, &tb->owners) {


if (sk != sk2 &&!inet_v6_ipv6only(sk2) && //sk和sk2不同,因为同一个套接字在bind和listen中都会调用get_port回调函数


(!sk->sk_bound_dev_if ||!sk2->sk_bound_dev_if || sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {


if (!reuse || !sk2->sk_reuse ||sk2->sk_state == TCP_LISTEN) {


const __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);


if (!sk2_rcv_saddr || !sk_rcv_saddr || sk2_rcv_saddr == sk_rcv_saddr) //如果有源地址的侦听套接字,那么源地址不同的也可以共享一个端口


break;


}


}


}


return node != NULL;


}
原创粉丝点击