LwIP - raw/callback API、协议栈API(sequential API)、BSD API(或者说 SOCKET API)

1、使用raw/callback API编程,用户编程的方法是向内核注册各种自定义的回调函数,回调函数是与内核实现交换的唯一方式。

recv_udp, accept_function, sent_tcp, recv_tcp, do_connected, poll_tcp, err_tcp!

 

2、协议栈API(sequential API)是基于raw/callback API实现的,它与内核交换的方式也只能通过回调。

netconn_new, netconn_delete, netconn_getaddr, netconn_connect, netconn_disconnect, netconn_listen, netconn_accept,

netconn_recv, netconn_send, netconn_write, netconn_close

注: netconn_send 是给UDP使用的。

netconn_write是给TCP使用的。但是tcp发送时,有三种选择:

(1)NETCONN_COPY 标志告诉协议栈将待发送数据拷贝到内核进程所属的内存空间,在这种情况下,会消耗系统的部分时间和内存资源,但是用户进程

可以在向内核提交数据后立即重新使用这些数据区域,甚至删除这些区域,而不必等待内核是否完全正确发送。如果用户没有设置该位,则内核构造发送

数据包是,会引用这些发送数据的内存区域,在这种情况下,用户进程不能再对这些数据进行修改,这种方式通常用在静态数据(ROM数据)的发送中。

对于非ROM数据的发送,用户应尽量设置NETCONN_COPY标志。

(2)NETCONN_MORE标志,当其置位时,组装这些数据的最后一个TCP报文段首部PSH标志将被设置,这样,数据在接收端将被尽快的递交给上层,而不会缓冲等待。

 

3、BSD API(或者说 SOCKET API),是Lwip设计者对sequential API函数进行了简单封装后的函数。

socket、bind、connect、listen、accept、sendto、write、recvfrom、read、close。

sendto、recvfrom:主要用于UDP,但是也可用于TCP。

write、read:主要用于TCP,但是也可用于UDP。



简介

lwIP提供了两套API:

1.底层的基于回调(callback)的raw API

2.高层的顺序模型的API(类似BSD socket)

    顺序模型的API为普通的顺序程序提供使用协议栈的API,和BSD风格的API很相似,也是基于阻塞的open-read-write-close模式。鉴于TCP/IP协议栈本身就基于时间的。所以TCP/IP代码和应用程序的代码必须在不同的线程中。

    而raw API可以让应用程序和TCP/IP协议栈代码结合的更紧密。程序的执行也是基于事件的,使用回调函数的机制。这种方式TCP/IP代码和应用代码运行在同一个线程中。

    实际上,顺序模型的API也是基于raw API实现的。

回调

    程序的执行是基于回调函数的,回调函数从传入的参数获取当前连接的状态。为回调函数设置连接状态参数的函数如下:

void tcp_arg(struct tcp_pcb *pcb, void *arg) ;

pcb是当前TCP连接的控制块,arg是将会传给回调函数的参数。

建立TCP连接

    TCP连接建立的方法和BSD socket很相似,通过tcp_new函数可以创建一个新的TCP标识(在raw API中是PCB这个结构--protocol control block)。PCB可以设置成监听一个连接或者明确地连接到一个主机。

     struct tcp_pcb *tcp_new(void);

创建一个新的PCB,如果返回NULL表示创建失败。

 

err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) ;

将pcb绑定到一个本地IP地址+端口。IP地址可以设置成IP_ADDR_ANY以绑定到所有本地IP地址。如果其他连接已经绑定到该端口则会返回ERR_USE,否则返回ERR_OK。

 struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb);

让pcb进入监听状态。当一个新的连接建立时,由tcp_accept指定的回调函数将被调用。该函数会返回一个新的pcb,作为参数传递的那个pcb会被释放。失败时返回NULL,此时参数的pcb将不会被释放。

 

struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) ;

类似于tcp_listen,但是会限制在等待连接的队列中的连接的数量(不能超过backlog),需要在lwipopts.h中将TCP_LISTEN_BACKLOG设置为1.

 void tcp_accepted(struct tcp_pcb *pcb);

告诉lwIP新的连接已经被接受,通常在接受回调函数中调用,通知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()函数是立即返回的,它不会等待连接真的被建立,当连接真正建立时它会调用第四个参数connectted函数,如果连接不能成功建立则connect函数的参数err会设置成对应的错误值。如果没有足够的空间将SYN请求入队列该函数会返回ERR_MEM,否则成功的话会返回ERR_OK。

 

发送数据

    TCP数据是通过tcp_write函数发送的:

 

 err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len, u8_t copy) ;

 

 

将dataptr指向的数据送到发送队列。len是发送数据的长度,copy参数表示是否允许数据拷贝。当发送的数据超过当前发送缓冲区或者发送队列的长度超过最大限制,该函数会返回ERR_MEM。发送队列中可用的字节数可以用tcp_sndbuf()函数获取。这个函数合适的用法是,发送不大于tcp_sndbuf()长度的字节数,如果返回ERR_MEM,程序等待发送队列数据空间足够后继续调用。

 

 void tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len));

指定数据被成功发送后(收到远程主机的响应信息)应该执行的回调函数。len参数表示上次ACK中确定的字节数。

 

 

接收数据

TCP数据的接收是基于回调的。程序指定当新的数据到来是应该执行的回调函数。

 

 

 void tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) ;

设置接收到数据时应该调用的回调函数。如果pbuf==NULL则证明远程主机已经关闭连接。如果没有错误,并且会点函数将返回ERR_OK时,必须首先释放pbuf。否则不要释放pbuf以便lwIP保存。

 void tcp_recved(struct tcp_pcb *pcb, u16_t len);

当程序接收完毕数据时调用,len是接收的数据长度。

 

关闭连接

 err_t tcp_close(struct tcp_pcb *pcb) ;


 void tcp_abort(struct tcp_pcb *pcb) ;

两个函数的不同在于,第二个函数永远不会出错~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值