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

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

原型: err_t  tcp_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))|| ip_addr_isany(ipaddr) || ip_addr_cmp(&(cpcb->local_ip), ipaddr)){ 
				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 中定义了:

 #define IP_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;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值