本帖最后由 xiaoqizi 于 2018-9-15 22:40 编辑
什么是回调函数? 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()函数返回NULL,如果这样的话,传入的PCB参数将不会被释放。 这个函数从原理上看也比较简单,首先是做一些必要的检查,判断原始pcb是否已经处于连接状态,如果没有则申请一块tcp_pcb类型的内存,将原始的必要的pcb内容复制到新的pcb中,设置新的pcb状态为LISTEN,释放原始的pcb,并将新pcb连接放入已监听队列。 - struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) 这个函数和tcp_listen()函数相同,只是限制了TCP监听队列连接个数,这个个数由backlog参数指定。为了使用它,你必须在你的lwipopt.h中设置TCP_LISTEN_BACKLOG=1。 - void tcp_accepted(struct tcp_pcb *pcb) 通知lwIP一个传入的连接已经被接受。通常这个函数在“accept()”函数的回调函数中被调用。这允许lwIP处理自身内部的任务。比如,允许更多传入的连接进入监听队列。 - void tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) 指定应在侦听连接上的一个新的连接到达时调用的回调函数。 - err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)); 设置打开连接的pcb连接到远程主机并发送初始的SYN段。 函数tcp_connect() 会立即返回;它并不等待这个连接是否被正确设置。相反的,当连接正确建立后它将调用第四个参数("connected"参数)指定的函数。如果这个连接不能正确的建立,可能是主机拒绝这个连接或者主机没有响应,"connected"函数将被调用并设置一个相应的参数。 当入队的SYN段内存不可用时,tcp_connect()函数能返回ERR_MEM,表示连接没有正确建立。如果SYN成功入队,tcp_connect()函数返回ERR_OK。 |