1、socket函数创建一个socket连接,此时该socket连接为主动式。
2、bind函数把socket与ip和端口绑定,并且把socket连接从 主动式 改为 被动式,成为服务端,只能够接受客户端的连接,不能发起连接。
3、listen函数开始监听socket,开始接受客户端的连接,不会阻塞(或者只会因为锁阻塞);backlog参数:建立连接的全连接队列大小限制;未完成三次握手的半连接队列有另外的参数限制
4、accpet函数从全连接队列取出 new sd,然后开始工作。默认可阻塞(浅度睡眠),可以在sd创建后设置 不阻塞 属性;
5、connet函数发起三次握手建立连接,在三次握手期间也分为阻塞和非阻塞两种。
ipv4源码参考:
1 static int inet_csk_wait_for_connect(struct sock *sk, long timeo) 2 { 3 struct inet_connection_sock *icsk = inet_csk(sk); 4 DEFINE_WAIT(wait); 5 int err; 6 7 /* 8 * True wake-one mechanism for incoming connections: only 9 * one process gets woken up, not the 'whole herd'. 10 * Since we do not 'race & poll' for established sockets 11 * anymore, the common case will execute the loop only once. 12 * 13 * Subtle issue: "add_wait_queue_exclusive()" will be added 14 * after any current non-exclusive waiters, and we know that 15 * it will always _stay_ after any new non-exclusive waiters 16 * because all non-exclusive waiters are added at the 17 * beginning of the wait-queue. As such, it's ok to "drop" 18 * our exclusiveness temporarily when we get woken up without 19 * having to remove and re-insert us on the wait queue. 20 */ 21 for (;;) { 22 prepare_to_wait_exclusive(sk_sleep(sk), &wait, 23 TASK_INTERRUPTIBLE); 24 release_sock(sk); 25 if (reqsk_queue_empty(&icsk->icsk_accept_queue)) 26 timeo = schedule_timeout(timeo); 27 sched_annotate_sleep(); 28 lock_sock(sk); 29 err = 0; 30 if (!reqsk_queue_empty(&icsk->icsk_accept_queue)) 31 break; 32 err = -EINVAL; 33 if (sk->sk_state != TCP_LISTEN) 34 break; 35 err = sock_intr_errno(timeo); 36 if (signal_pending(current)) 37 break; 38 err = -EAGAIN; 39 if (!timeo) 40 break; 41 } 42 finish_wait(sk_sleep(sk), &wait); 43 return err; 44 }
5、connet函数从
源码参考:
ipv4代码路径:linux/net/ipv4/af_inet.c
初始化代码:
1 static int __init inet_init(void) 2 ---proto_register(&tcp_prot, 1); 3 ---inet_register_protosw(q);
关键数据结构的值,sd的操作全部在里面:
1 static struct inet_protosw inetsw_array[] = 2 { 3 { 4 .type = SOCK_STREAM, 5 .protocol = IPPROTO_TCP, 6 .prot = &tcp_prot, 7 .ops = &inet_stream_ops, 8 .flags = INET_PROTOSW_PERMANENT | 9 INET_PROTOSW_ICSK, 10 }, 11 12 { 13 .type = SOCK_DGRAM, 14 .protocol = IPPROTO_UDP, 15 .prot = &udp_prot, 16 .ops = &inet_dgram_ops, 17 .flags = INET_PROTOSW_PERMANENT, 18 }, 19 20 { 21 .type = SOCK_DGRAM, 22 .protocol = IPPROTO_ICMP, 23 .prot = &ping_prot, 24 .ops = &inet_sockraw_ops, 25 .flags = INET_PROTOSW_REUSE, 26 }, 27 28 { 29 .type = SOCK_RAW, 30 .protocol = IPPROTO_IP, /* wild card */ 31 .prot = &raw_prot, 32 .ops = &inet_sockraw_ops, 33 .flags = INET_PROTOSW_REUSE, 34 } 35 };