[转载]lwIP RAW TCP/IP接口
2013-01-05 14:39阅读:
lwIP RAW
TCP/IP接口
作者:
Adam Dunkels, Leon Woestenberg, Christiaan
Simons
lwIP为使用TCP/IP协议通信的应用程序编程提供了两种接口接口(APIs):
*
低层次的称之为'core' / 'callback'
或者 'raw' API
*
高层次的称之为
'sequential' API
lwIP 'sequential'
API为使用TCP/IP协议栈编程提供符合常规的、通用的途径,它与BSD socket
API非常相似。程序的执行过程同样是基于'open-read-write-close'模型的。从本质上讲,TCP/IP协议栈的通信过程是事件驱动的,因此,TCP/IP的代码和用户应用程序的代码必须在不同的线程里面。
**以下内容讨论'RAW' API**
RAW
IP允许应用程序和TCP/IP代码紧密结合,程序的执行是基于在TCP/IP内核中被调用的回调函数事件驱动的。TCP/IP内核和应用程序可以运行在同一线程。lwIP 'sequential'
API接口会消耗大量的CPU资源,它并不适用于小型嵌入式系统,因为它必须运行在多线程环境中。
RAW
API不仅执行速度快,而且消耗的内存资源更少。它的缺点是应用程序编写相对较难并不易理解。尽管如此,这种方式仍是资源较少的嵌入式系统的首选方法。
不同的应用程序中我们可以同时使用这两种APIs,实际上'sequential'
API就是由RAW
API封装后得到的。
什么是回调函数?
RAW
API是基于回调函数所驱动的。每一个回调函数实际上只是一个普通的C函数,这个函数在TCP/IP内核中被调用。每一个回调函数都作为一个参数传递给当前TCP或UDP连接。而且,为了能够保存程序的特定状态,可以向回调函数传递一个指定的状态,并且这个指定的状态是独立于TCP/IP协议栈的。
--应用程序设置状态函数
- void
tcp_arg(struct tcp_pcb *pcb, void *arg)
指定传给所有回调函数的特定状态参数。参数'pcb'指当前TCP连接控制块,'arg'指传递给回调函数的参数。
--TCP连接函数
这些函数用于建立连接,它们与'sequential'
API以及BSD socket
API非常相似。使用tcp_new()函数建立一个新的TCP标识符(也就是协议控制块-PCB)。这个PCB可以用来监听一个外来的连接(译注:作为服务器)也可以连接到另一个主机(译注:作为客户端)。
- struct tcp_pcb
*tcp_new(void)
创建一个新的连接标识符(PCB)。如果没有有效的存储空间创建这个新的pcb,返回NULL。
译注:这个函数创建一个TCP协议控制块,但并不把它放到任何TCP
PCB列表,直到使用tcp_bind()函数绑定。Tcp_new()函数会调用tcp_alloc函数来动态申请一块内存并初始化它,之后将这块内存的首地址返回给tcp_new()函数,如果动态内存不成功的话返回NULL。
- err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr
*ipaddr,
u16_t
port)
给pcb绑定一个本地IP地址和端口号。如果参数'ipaddr'为IP_ADDR_ANY,则为这个pcb绑定任意本地IP地址。
译注:这个函数的大部分代码用于检验给出的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为广播地址,也就是任意地址的意思。
- struct tcp_pcb
*tcp_listen(struct tcp_pcb *pcb)
指定一个PCB进入监听状态。当一个远端连接访问时,函数
tcp_accept()指定的回调函数将被调用。在调用这个函数之前一定要使用tcp_bind()函数绑定一个本地IP和端口号。
tcp_listen()
函数返回一个新的连接标识符,原始的pcb会被释放,这是为了节省内存,使之更适合小内存系统。
如果监听连接的内存无效,tcp_listen()函数返回