LwIP Application Developers Manual6---Application API layers
1.前言
lwIP提供3种应用编程接口来跟TCP/IP内核通信,如下所示:
- 低水平的内核/回调或raw API
- 2个高水平序列API:
1) netconn API
2) socket API(为了兼容POSIX/BSD-socket)
2.选择合适的应用编程接口
- 序列API
序列API提供了一种普通、有序的程序来使用lwIP内核。它与BSD的socket API非常相似。该序列API的模型是建立在阻塞的打开-读-写-关闭(open-read-write-close)模式上。
由于TCP/IP栈本质上是基于事件的,TCP/IP的代码和应用程序必须适应在不同的可执行的上下文(线程)内。
- RAW API
当原始(raw)和序列API混合使用时,你要很小心了:rawI函数只能被主tcpip_thread调用。注册回调函数(或初始化一个pcb)也一定要在那个上下文中完成(比如,在启动时调用tcpip_init_callback时或运行时调用tcpip_callback)。
- 选择合适的API的几点建议
1) netconn-和raw-API只属于lwIP本身,用这些API写的代码并不能移植并重新使用在其它协议栈上。
2) socket API与1)相反,用该API写的代码可以付出较小的工作量就可以移植到posix协议栈上。
3) socket-和netconn-API是序列API,该API需要多线程间的支持(一个线程用于使用API,一个线程用来为协议栈处理定时器、接收到的数据包等)
4) RAW API使用回调函数的机制(比如,当新的数据到达时,应用程序的回调函数被调用)。如果你习惯用序列API编程,那么你使用原始API编程会变得比较困难。
5) RAW API由于它不需要线程间的切换可以得到最好的性能。
6) raw-和netconn-API对于发送和接收支持零复制(尽管DMA使能,MACs可以防止对接收的数据进行复制)
3.原始(raw/native)API
3.1 原始API介绍
原始API是一个基于事件驱动的,该API也可以不需要操作系统的支持而且不需要重复复制接收和发送的数据。
内核协议栈经常使用原始API来进行各种协议间的交互。当lwIP没有在操作系统上运行时,只能使用原始API来编程。
应用程序是靠回调函数实现的,当与应用程序相关活动发生时该回调函数被lwIP内核调用。
一个特定的应用可以通过注册基于事件的回调函数被通知,比如刚接收到数据,发送数据,错误通知,查询定时器是否超时,连接关闭,等等。
一个应用可以提供一个回调函数来处理所有的事件。
不要将lwIP的原始API与raw ethernet或IP sockets相混淆。
原始API是lwIP网络协议栈(包括tcp和udp)的一组接口,而原始以太网或IP sockets 则关注处理raw ethernet或IP 数据而不是tcp的连接或udp的数据包。
3.2 与多线程相关的问题
当在一个多线程环境中运行时,由于原始API并没有提供并行访问保护(比如pbuf-和内存管理函数),原始API函数只能被内核线程(tcpip-thread)调用。
由于所有的数据包(输入和输出)和定时器的处理都在同一个可执行上下文中,原始API从不会被阻塞。
3.3 模块
原始API可以访问如下协议:
- 网络层协议(IPv4/IPv6)
- 传输层协议:UDP、TCP、RAW IP、ICMP、IGMP
- 应用层协议:DHCP、AUTOIP、SNMP、DNS(自1.3.0起)
- 网络接口管理函数
- 内存和数据包缓存管理函数(相关的内存池和堆栈)
- 操作系统抽象层
3.4 函数
相关函数的正式描述可以在doc/rawapi.txt找到。如下是一些附加备注:
- void tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err));
说明:tcp_accept()必须在tcp_listen()后调用,由于:
(1)如果先调用tcp_accept()很可能导致丢失当调用tcp_listen(),原因是tcp_listen()分配一个新的pcb但实际上并没有从老的pcb复制相关的内容(pcb-accept)(请查阅tcp_listen_with_backlog()在lwip/src/core/tcp.c)
(2)所有lwIP原始API都在一个线程中运行,接收到的数据包并不会在tcp_listen()和tcp_accept()之间马上被处理。在pcb被tcp_accept()正确配置前,调用tcp_listen()会导致接受连接而不产生危险。
- void tcp_setprio(struct tcp_pcb *pcb, u8_t prio);
这个函数并没有被doc/rawapi.txt记录,但是它经常被当例子来使用而没有合适的说明。当内存不够时lwIP将关掉低优先级的tcp连接。这个函数设置了连接的优先级。
- err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
这是一个接收回调函数。该函数可以返回一个错误值。当该函数的返回值与ERR_OK不相同时,数据将被lwIP所缓存。
在下一次调用fasttmr()时,这个数据还会再次发送给应用程序,这样应用程序可以取走该数据或再次拒绝它。
如果有数据等待处理,而又有新的数据包到达,那么该连接将会继续保存应用程序拒绝的数据,该回调函数会被再次调用,并试图发送挂起的数据。
如果应用程序再次拒绝刚接收到的数据那么该数据就会被丢弃。(相关的源文件:tcp.c和tcp_in.c,搜索TCP_EVENT_RECV和refused_data)。
4. Netconn API
4.1 简介
netconn API是一个序列API,该API被设计来更容易使用lwIP协议栈(与基于事件驱动的原始API相比),而且保留零复制的功能。
4.2 在多线程下的执行
使用netconn API,由于该API要求使用线程,必须需要操作系统的支持。所有的数据包处理(输入和输出)都在一个相关的线程内完成(比如,tcpip-thread)。
使用netconn API的应用线程来通过消息邮箱和信号量和内核线程进行通信
4.3 从应用的角度看netconn API
使用netconn API的应用程序可以使用api.h (netconn_*() functions) and netbuf.h(netbuf_*() functions)中定义的所有函数
netconn API支持的传输层协议包括UDP,TCP和RAW IP
(1)应用可以使用如下函数来跟netconn一起工作
- netconn_new() – create a new connection
- netconn_new_with_callback() – create new connection
- netconn_new_with_proto_and_callback() - create a new connection
- netconn_delete() - delete an existing connection
- netconn_bind() - bind a connection to a local port/ip
- netconn_connect() - connect a connection to a remote port/ip
- netconn_disconnect() - disconnect a connection from a remote port/ip
- netconn_send() - send data to the currently connected remote port/ip (not applicable for TCP)
- netconn_sendto() - send data to a specified remote port/ip (not applicable for TCP)
- netconn_recv() - receive data from a netconn
- netconn_set_recvtimeout() – set a receive timeout value for a netconn structure
- netconn_get_recvtimeout()– get the receive timeout value for a netconn structure
(2)对TCP连接,支持一些额外的功能
- netconn_listen() - set a TCP connection into listen mode
- netconn_accept() - accept an incoming connection on a listening TCP connection
- netconn_write() - send data on a connected TCP netconn
- netconn_close() - close a TCP netconn without deleting it
(3)为应用程序提供的更高层协议支持
- netconn_gethostbyname() - Does a name lookup (queries dns server if req'd) to resolve a host name to an IP address
- netconn_join_leave_group() - basic IGMP multicast support
(4)发送和接收采用netbufs
netbufs具有零复制接收和发送数据的功能。如下函数可以与netbufs一起工作
- netbuf_new()
- netbuf_delete()
- netbuf_alloc()
- netbuf_free()
- netbuf_ref()
- netbuf_chain()
- netbuf_len()
- netbuf_data()
- netbuf_copy()
- netbuf_next()
- netbuf_first()
4.4 Nonblocking IO
从2010年2月的CVS版本,netconn API支持非阻塞的连接
你可以创建自己的回调函数处理netconn_evt事件,如下所示:
- conn = netconn_new_with_callback(NETCONN_TCP, your_callback_function)
- netconn_set_nonblocking(conn, 1)
- netconn_connect(...) -> does not block (as above)
-通过NETCONN_EVT_SENDPLUS (连接) or NETCONN_EVT_ERROR(连接失败)事件等待your_callback_function()函数被调用。
留意线程间的切换:回调函数被tcpip-thread线程调用,并不是在你的应用线程
5. Socket API
5.1 函数
新加入shutdown()(1.3.0)函数并不适合执行。
5.2 外部参考连接
LwIP Application Developers Manual6---Application API layers的更多相关文章
- LwIP Application Developers Manual1---介绍
1.前言 本文主要是对LwIP Application Developers Manual的翻译 2.读者(应用开发手册的读者) 谁适合读这份手册 网络应用的开发者 想了解lwIP的网络应用开发者 阅 ...
- LwIP Application Developers Manual2---Protocols概览
1.前言 本文是对LwIP Application Developers Manual的翻译 lwIP是模块化的并支持广泛的协议,这些大部分协议可以被裁减从而减小代码的尺寸 2.协议概览 链路层和网络 ...
- Building Applications with Force.com and VisualForce (DEV401) (二) : Application Essentials:Designing Application on the Force.com Platform
Dev 401-002:Application Essentials:Designing Application on the Force.com Platform Course Objectives ...
- Win32 Console Application、Win32 Application、MFC三者之间的联系和区别
转自:http://blog.csdn.net/c_base_jin/article/details/52304845 在windows编程中,我们或多或少都听说这三个名称,分别是Win32 Cons ...
- Jsoup问题---获取http协议请求失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.
Jsoup问题---获取http协议请求失败 1.问题:用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不 ...
- Jsoup获取部分页面数据失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.
用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不符合要求. 请求代码如下: private static ...
- application/json和application/x-www-form-urlencoded使用选择
一.参考资料 选application/x-www-form-urlencoded还是application/json? @RequestBody应用 二.理解 1.@RequestBody的作用 注 ...
- SpringBoot application.properties (application.yml)优先级从高到低
SpringBoot application.properties(application.yml) 优先级从高到低 SpringBoot配置文件优先级从高到低 =================== ...
- jdb--gdb---java 远程调试(java application与web application)
命令比较 gdb jdb bt where del clear stop brea ...
随机推荐
- springboot配置jsp
spring.mvc.view.prefix= /WEB-INF/jsp/ spring.mvc.view.suffix= .jsp pom.xml <!--jsp支持--> <!- ...
- Hadoop端口说明
Hadoop端口说明: 默认端口 设置位置 描述信息 8020 ...
- Nginx 简单安装
关于nginx的介绍:http://baike.baidu.com/link?url=UZjpP8y4MUgrjqACfxd7c3Cm4L8PnJsKkxSJQ3CrRcKZUjkkl4zGNs6Pr ...
- Hadoop记录-NameNode优化
1.NameNode启动过程 加载FSImage: 回放EditLog: 执行CheckPoint(非必须步骤,结合实际情况和参数确定,后续详述): 收集所有DataNode的注册和数据块汇报. 采用 ...
- 使用rvm安装与切换Ruby
列出已知的 Ruby 版本 rvm list known安装一个 Ruby 版本 rvm install 2.3.1 --disable-binary这里安装了最新的 2.2.0, rvm list ...
- 【转】Linux C下非特定波特率的配置和使用
https://blog.csdn.net/jinhongdu/article/details/43413071 对于非标准的任意波特率需要用ioctl(fd, TIOCGSERIAL, p)和i ...
- 阅读:重新介绍 JavaScript(JS教程)
这篇文章是记录自己阅读重新介绍 JavaScript(JS 教程)的记录和个人体会 在线调试代码工具:https://codepen.io/pen 引言 分歧根源:名字Javascript和Java有 ...
- HDU 1030(三角数阵 数学)
题意是问在给定的三角形数阵中从一个数到另一个数所要跨过的边数. 最初的时候很迷,除了发现每层的数字个数与层数间的关系和每层数最后一个数与层数的关系外什么也没看出来,打算先求出数字所在的层数,然后计算到 ...
- Golang入门教程(十)内建函数
比较常用的内建函数 参考: http://blog.csdn.net/liumiaocn/article/details/54804074
- Golang入门教程(六)关键字和数据类型
在 Go 编程语言中,数据类型用于声明函数和变量. 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存. 一.25个关键字 二.18 ...