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一起工作

(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一起工作

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的更多相关文章

  1. LwIP Application Developers Manual1---介绍

    1.前言 本文主要是对LwIP Application Developers Manual的翻译 2.读者(应用开发手册的读者) 谁适合读这份手册 网络应用的开发者 想了解lwIP的网络应用开发者 阅 ...

  2. LwIP Application Developers Manual2---Protocols概览

    1.前言 本文是对LwIP Application Developers Manual的翻译 lwIP是模块化的并支持广泛的协议,这些大部分协议可以被裁减从而减小代码的尺寸 2.协议概览 链路层和网络 ...

  3. 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 ...

  4. Win32 Console Application、Win32 Application、MFC三者之间的联系和区别

    转自:http://blog.csdn.net/c_base_jin/article/details/52304845 在windows编程中,我们或多或少都听说这三个名称,分别是Win32 Cons ...

  5. Jsoup问题---获取http协议请求失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.

    Jsoup问题---获取http协议请求失败 1.问题:用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不 ...

  6. Jsoup获取部分页面数据失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.

    用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不符合要求. 请求代码如下: private static ...

  7. application/json和application/x-www-form-urlencoded使用选择

    一.参考资料 选application/x-www-form-urlencoded还是application/json? @RequestBody应用 二.理解 1.@RequestBody的作用 注 ...

  8. SpringBoot application.properties (application.yml)优先级从高到低

    SpringBoot application.properties(application.yml) 优先级从高到低 SpringBoot配置文件优先级从高到低 =================== ...

  9. jdb--gdb---java 远程调试(java application与web application)

    命令比较     gdb              jdb     bt             where     del           clear     stop         brea ...

随机推荐

  1. 剑指Offer_编程题_16

    题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. /* struct ListNode { int val; struct ListNode *n ...

  2. zookeeper 介绍与集群安装

    zookeeper 介绍 ZooKeeper是一个分布式开源框架,提供了协调分布式应用的基本服务,它向外部应用暴露一组通用服务——分布式同步(Distributed Synchronization). ...

  3. nGrinder TestRunner http post json

    s nGrinder学习笔记 — post请求 https://blog.csdn.net/meyoung01/article/details/50435881 import HTTPClient.H ...

  4. Centos 6\7下yum安装R

    在linux下安装软件不如windows方便,在windows下我们一般针对可安装的文件(如R.exe)直接双击运行就可以了.而在linux下我们首先要学会使用安装软件的专门工具如centos下的rp ...

  5. 记录一次php连接mssql的配置

    记录一次php连接mssql的配置 在现有php环境中,php连接mssql数据库失败,tsql 连接正常. 确认问题在php环境上. 网上有个同仁总结的很好,https://blog.csdn.ne ...

  6. JAVA-String,StringBuilder,StringBuffer例子(基础必备)

    package com.net.xinfang.reflect; import java.io.UnsupportedEncodingException; /** * String不属于8种基本数据类 ...

  7. Web API中的模型验证

    一.模型验证的作用 在ASP.NET Web API中,我们可以使用 System.ComponentModel.DataAnnotations 命名空间中的属性为模型上的属性设置验证规则. 一个模型 ...

  8. 解决Navicat 出错:1130-host . is not allowed to connect to this MySql server,MySQL

    1. 改表法. 可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入MySQL后,更改 "mysql" 数据库里的 " ...

  9. appcms SSRF 绕过漏洞[转载]

    漏洞 <?php if(isset($_GET['url']) && trim($_GET['url']) != '' && isset($_GET['type' ...

  10. 在 CentOS6 上安装 Zabbix3.0 Agent 并开启客户端自动注册

    #!/bin/bash # # .配置yum源 # cat /etc/redhat-release |grep -i centos |grep '6.[[:digit:]]' &>/de ...