1、socket函数创建一个socket连接,此时该socket连接为主动式。 fd(int)->fd(struct fd)->file->sock;sock->file

2、bind函数把socket与ip和端口绑定,并且把socket连接从 主动式 改为 被动式,成为服务端,只能够接受客户端的连接,不能发起连接。

3、listen函数开始监听socket,开始接受客户端的连接,不会阻塞(或者只会因为锁阻塞);backlog参数:建立连接的全连接队列大小限制;未完成三次握手的半连接队列有另外的参数限制

4、accpet函数从全连接队列取出 new sd,,然后开始工作。默认可阻塞(浅度睡眠),可以在sd创建后设置 不阻塞 属性;https://blog.csdn.net/tanyjin/article/details/69403220

5、connet函数发起三次握手建立连接,在三次握手期间也分为阻塞和非阻塞两种。

ipv4源码参考:

 static int inet_csk_wait_for_connect(struct sock *sk, long timeo)
{
struct inet_connection_sock *icsk = inet_csk(sk);
DEFINE_WAIT(wait);
int err; /*
* True wake-one mechanism for incoming connections: only
* one process gets woken up, not the 'whole herd'.
* Since we do not 'race & poll' for established sockets
* anymore, the common case will execute the loop only once.
*
* Subtle issue: "add_wait_queue_exclusive()" will be added
* after any current non-exclusive waiters, and we know that
* it will always _stay_ after any new non-exclusive waiters
* because all non-exclusive waiters are added at the
* beginning of the wait-queue. As such, it's ok to "drop"
* our exclusiveness temporarily when we get woken up without
* having to remove and re-insert us on the wait queue.
*/
for (;;) {
prepare_to_wait_exclusive(sk_sleep(sk), &wait,
TASK_INTERRUPTIBLE);
release_sock(sk);
if (reqsk_queue_empty(&icsk->icsk_accept_queue))
timeo = schedule_timeout(timeo);
sched_annotate_sleep();
lock_sock(sk);
err = ;
if (!reqsk_queue_empty(&icsk->icsk_accept_queue))
break;
err = -EINVAL;
if (sk->sk_state != TCP_LISTEN)
break;
err = sock_intr_errno(timeo);
if (signal_pending(current))
break;
err = -EAGAIN;
if (!timeo)
break;
}
finish_wait(sk_sleep(sk), &wait);
return err;
}

5、connet函数从

源码参考:

ipv4代码路径:linux/net/ipv4/af_inet.c

初始化代码:

 static int __init inet_init(void)
---proto_register(&tcp_prot, );
---inet_register_protosw(q);

关键数据结构的值,sd的操作全部在里面:

 static struct inet_protosw inetsw_array[] =
{
{
.type = SOCK_STREAM,
.protocol = IPPROTO_TCP,
.prot = &tcp_prot,
.ops = &inet_stream_ops,
.flags = INET_PROTOSW_PERMANENT |
INET_PROTOSW_ICSK,
}, {
.type = SOCK_DGRAM,
.protocol = IPPROTO_UDP,
.prot = &udp_prot,
.ops = &inet_dgram_ops,
.flags = INET_PROTOSW_PERMANENT,
}, {
.type = SOCK_DGRAM,
.protocol = IPPROTO_ICMP,
.prot = &ping_prot,
.ops = &inet_sockraw_ops,
.flags = INET_PROTOSW_REUSE,
}, {
.type = SOCK_RAW,
.protocol = IPPROTO_IP, /* wild card */
.prot = &raw_prot,
.ops = &inet_sockraw_ops,
.flags = INET_PROTOSW_REUSE,
}
};
05-21 00:48