`
yidongkaifa
  • 浏览: 4038615 次
文章分类
社区版块
存档分类
最新评论

lwIP(V1.0.0) RAW API函数源码分析2----tcp_bind()函数

 
阅读更多

位于:位于:lwip-x.x.x/src/core/tcp.c

原型: err_ttcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)

功能:绑定连接到一个本地端口号和IP地址.

函数源码:

/**
 * Binds the connection to a local port number and IP address. If the
 * IP address is not given (i.e., ipaddr == NULL), the IP address of
 * the outgoing network interface is used instead.
 *IP地址没有给出(即ipaddr==NULL),则IP地址由输出网络接口代替
 * @param pcb the tcp_pcb to bind (no check is done whether this pcb is
 *        already bound!)
 * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind
 *        to any local address
 * @param port the local port to bind to
 * @return ERR_USE if the port is already in use
 *         ERR_OK if bound 成功绑定
 */
err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
  struct tcp_pcb *cpcb;

  LWIP_ERROR("tcp_connect: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);	

  if (port == 0) {
    port = tcp_new_port();	//返回一个新的(自由的)本地TCP端口号
  }
  /* Check if the address already is in use. */
  /* Check the listen pcbs. */
/* 检查*/
  for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;/*注1 */
      cpcb != NULL; cpcb = cpcb->next) {
    if (cpcb->local_port == port) {
      if (ip_addr_isany (&(cpcb->local_ip)) /*已监听pcb列表中IP地址全为0或没有分配IP地址,则函数返回1*/||
          ip_addr_isany(ipaddr) /*检验参数IP地址*/||
          ip_addr_cmp(&(cpcb->local_ip), ipaddr)) /*检验参数IP和已监听pcb列表中IP地址是否相同*/{
        return ERR_USE;	//返回端口已被使用信息
      }
    }
  }
  /* Check the connected pcbs. 检查当前连接的pcbs*/
  for(cpcb = tcp_active_pcbs;
      cpcb != NULL; cpcb = cpcb->next) {
    if (cpcb->local_port == port) {
      if (ip_addr_isany(&(cpcb->local_ip)) ||
          ip_addr_isany(ipaddr) ||
          ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
        return ERR_USE;
      }
    }
  }
  /* Check the bound, not yet connected pcbs.检查已绑定的还没有连接的pcbs */
  for(cpcb = tcp_bound_pcbs; cpcb != NULL; cpcb = cpcb->next) {
    if (cpcb->local_port == port) {
      if (ip_addr_isany(&(cpcb->local_ip)) ||
          ip_addr_isany(ipaddr) ||
          ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
        return ERR_USE;
      }
    }
  }
  /* @todo: until SO_REUSEADDR is implemented (see task #6995 on savannah),
   * we have to check the pcbs in TIME-WAIT state, also: */
  for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
    if (cpcb->local_port == port) {
      if (ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
        return ERR_USE;
      }
    }
  }

  if (!ip_addr_isany(ipaddr)) {
    pcb->local_ip = *ipaddr;	//IP地址给当前连接的pcb 
  }
  pcb->local_port = port;
  TCP_REG(&tcp_bound_pcbs, pcb);	//将当前pcb放入已绑定tcp_pcb列表
  LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"/n", port));
  return ERR_OK;
}

分析:这个函数的大部分代码用于检验给出的IP地址和端口号是否合适,如果合适则将给出的IP地址和端口号赋给当前PCB,更新已绑定tcp_pcb列表并返回ERR_OK.如果给出的参数不合适,则返回ERR_USE.

参数ipaddr如果为IP_ADDR_ANY,表示绑定到任何本地地址,那么IP_ADDR_ANY是什么呢?在lwip-1.3.0/src/include/ipv4/lwip/ip_addr.h中定义了:

#defineIP_ADDR_ANY((struct ip_addr *)&ip_addr_any)

ip_addr_any是一个ip_addr型变量,在lwip-1.3.0/src/core/ipv4/ip_addr.c中有如下声明:

#define IP_ADDR_ANY_VALUE 0x00000000UL

const struct ip_addr ip_addr_any = { IP_ADDR_ANY_VALUE };

所以, IP_ADDR_ANY是等于0x00000000UL的.在IP地址上规定0.0.0.0为广播地址,也就是任意地址的意思.

注1:在tcp.h中有如下定义:

/* The TCP PCB lists. TCP PCB列表*/

union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state.进入监听状态的所有TCP PCB列表*/

struct tcp_pcb_listen *listen_pcbs;

struct tcp_pcb *pcbs;

};

extern union tcp_listen_pcbs_t tcp_listen_pcbs;

转载自:http://blog.csdn.net/zhzht19861011/article/details/6188400
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics