码迷,mamicode.com
首页 > 其他好文 > 详细

lwip socket探秘之listen

时间:2014-12-30 23:25:02      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:

一个基本的socket建立顺序是
Server端:
  • socket()
  • bind()
  • listen()
  • accept()
  • recv()
Client端:
  • socket()
  • connect()
  • send()
 
本文着重介绍Server端的listen()过程。
 
用户使用socket,调用listen()时,实际调用的是lwip里的lwip_listen()。代码如下
 1 /**
 2 * Set a socket into listen mode.
 3 * The socket may not have been used for another connection previously.
 4 *
 5 * @param s the socket to set to listening mode
 6 * @param backlog (ATTENTION: need TCP_LISTEN_BACKLOG=1)
 7 * @return 0 on success, non-zero on failure
 8 */
 9 int
10 lwip_listen(int s, int backlog)
11 {
12   struct lwip_socket *sock;
13   err_t err;
14 .............
15   sock = get_socket(s); // 根据socket号(面向用户的socket标识)得到lwip内部的socket descriptor
16   if (!sock)
17     return -1;
18 ...............
19   err = netconn_listen_with_backlog(sock->conn, backlog); // 接下来看这个函数
20 ...............
21   return 0;
22 }

netconn_listen_with_backlog本身内容很少,主要是向下一连串调用:

netconn_listen_with_backlog
     =>do_listen
          =>tcp_listen
               =>tcp_listen_with_backlog
 
tcp_listen_with_backlog这个函数才是真正做了重要工作的地方。
 1 /**
 2 * Set the state of the connection to be LISTEN, which means that it
 3 * is able to accept incoming connections. The protocol control block
 4 * is reallocated in order to consume less memory. Setting the
 5 * connection to LISTEN is an irreversible process.
 6 *
 7 * @param pcb the original tcp_pcb
 8 * @param backlog the incoming connections queue limit
 9 * @return tcp_pcb used for listening, consumes less memory.
10 *
11 * @note The original tcp_pcb is freed. This function therefore has to be
12 *       called like this:
13 *             tpcb = tcp_listen(tpcb);
14 */
15 struct tcp_pcb *
16 tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
17 {
18   struct tcp_pcb_listen *lpcb;
19 
20   LWIP_UNUSED_ARG(backlog);
21   LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL);
22 
23   /* already listening? */
24   if (pcb->state == LISTEN) {
25     return pcb;
26   }
27   lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN); // 新建了一个pcb,后面会把原来的pcb free掉
28   if (lpcb == NULL) {
29     return NULL;
30   }
31   lpcb->callback_arg = pcb->callback_arg; // 新pcb继承旧pcb的一些内容
32   lpcb->local_port = pcb->local_port;
33   lpcb->state = LISTEN; // 因为用户调用了listen(),所以这个新pcb的状态是LISTEN
34   lpcb->so_options = pcb->so_options;
35   lpcb->so_options |= SOF_ACCEPTCONN;
36   lpcb->ttl = pcb->ttl;
37   lpcb->tos = pcb->tos;
38   ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
39   TCP_RMV(&tcp_bound_pcbs, pcb);
40   memp_free(MEMP_TCP_PCB, pcb); // free掉旧的pcb
41 #if LWIP_CALLBACK_API
42   lpcb->accept = tcp_accept_null;
43 #endif /* LWIP_CALLBACK_API */
44 #if TCP_LISTEN_BACKLOG
45   lpcb->accepts_pending = 0;
46   lpcb->backlog = (backlog ? backlog : 1);
47 #endif /* TCP_LISTEN_BACKLOG */
48   TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb); // 把新pcb挂到tcp_listen_pcbs这个链表里
49   return (struct tcp_pcb *)lpcb;
50 }
注意阅读函数上方的注释,这些注释简要的介绍了函数的作用,写的都非常有用。
tcp_listen_with_backlog这个函数主要是重新开辟了一个pcb代替旧的pcb(出于节省空间的考虑),将新pcb的状态设置为LISTEN,并将其挂在lwip里的tcp_listen_pcbs这个链表里。
 
 

lwip socket探秘之listen

标签:

原文地址:http://www.cnblogs.com/codingfun/p/4186343.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!