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 ...
随机推荐
- okhttp post form表单
OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); FormBody formBody = new FormBody.Bui ...
- 【SQL】SQL中on条件与where条件的区别
#前言 数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1.on条件是在生成临时表时 ...
- 【C#】C#格式化文件大小
/// <summary> /// 格式化文件大小的C#方法 /// </summary> /// <param name="filesize"> ...
- cmd命令对java程序进行编译时出现:编码GBK的不可映射字符
原因:由于JDK是国际版的,在编译的时候,如果我们没有用-encoding参数指定JAVA源程序的编码格式,则java.exe首先获得我们才做系统默认采用的编码格式,也即在编译JAVA程序时,若我们不 ...
- C++回顾day02---<拷贝构造函数:重点>
一:补充---无参构造函数(默认无参构造函数)在实例化对象时注意点 (一)若没有写构造函数,则类会含有一个默认无参构造函数 (二)若自定义一个构造函数,则类不会提供默认构造函数 class A { p ...
- 4.Zuul-限流
令牌桶 限流流程图: RateLimitFilter : package com.wangfajun.filter; import com.alibaba.fastjson.JSON; import ...
- Linux防火墙开放端口
# vi /etc/sysconfig/iptables-A INPUT -m state --state NEW -m tcp -p tcp --dport -j ACCEPT -A INPUT - ...
- Golang入门教程(十五)指针
什么是指针? 指针是一个变量,用于存储另一个变量的内存地址. 在上面的例子中,变量b的值是156,存储在内存地址0x1040a124. 变量a包含b的地址. 可以说现在a指向b. 声明指针 指向类型 ...
- while循环、格式化输出、运算符和编码初识
while循环 1. while循环的结构 while 条件: 执行语句1 执行语句2 i = 0 while i < 10: print(i) i += 1 运行结果 0 1 2 3 4 5 ...
- MyEclipse2017 隐藏回车换行符
Preferences->Text Editor->Show Whitespace characters(configure visibility)->Transparency Le ...