打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
lwip socket探秘之listen

 http://www.cnblogs.com/codingfun/p/4186343.html

2014
一个基本的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 int10 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 descriptor16   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 be12 *       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的状态是LISTEN34   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掉旧的pcb41 #if LWIP_CALLBACK_API42   lpcb->accept = tcp_accept_null;43 #endif /* LWIP_CALLBACK_API */44 #if TCP_LISTEN_BACKLOG45   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这个链表里。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
搞了半天,终于弄懂了TCP Socket数据的接收和发送,太难
为什么服务端程序都需要先 listen 一下?
TR2021_0000偶发数据库连接异常问题排查
高性能网络编程3
linux的Listen调用详解
socket原理详解
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服