LwIP Application Developers Manual11---Initializing lwIP
1.前言
2.Initialization for simple lwIP
查看doc/rawapi.txt来获得更多官方信息
#if NO_SYS
/* Network interface variables */
struct ip_addr ipaddr, netmask, gw;
struct netif netif;
/* Set network address variables */
IP4_ADDR(&gw, ,,,);
IP4_ADDR(&ipaddr, ,,,);
IP4_ADDR(&netmask, ,,,);
/* The lwIP single-threaded core: initialize the network stack */
lwip_init();
#else
/* lwIP in a multi-threaded system: initialize the network stack */
tcpip_init(tcpip_init_done, tcpip_init_done_param);
/* implicitly calls lwip_init();
start new thread calls tcpip_init_done(tcpip_init_done_param);
when tcpip init done tcpip_init_done and tcpip_init_done_param are user-defined (may be NULL). */
/* todo: wait for tcpip_init_done() ? */
#endif
/* Bring up the network interface */
/* Hint: netif_init(); was already called by lwip_init(); above */
netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ethhw_init, ethernet_input);
/* ethhw_init() is user-defined */
/* use ip_input instead of ethernet_input for non-ethernet hardware */
/* (this function is assigned to netif.input and should be called by the hardware driver) */
netif_set_default(&netif);
netif_set_up(&netif);
更多关于tcpip_init的详细信息请查看Initialization using tcpip.c。关于网络接口的管理详情请看Network interfaces management。
在初始化完后,会发生什么呢?你可以继续阅读lwIP with or without an operating system。完整的例子可以在contrib/ports/unix/proj/路径中找到。
3. Initialization using tcpip.c
如果你打算使用tcpip线程,下面是lwIP初始化的例子:
#include "lwip/tcpip.h" struct netif my_netif; err_t my_ip_init(struct ip_addr *ipaddr,
struct ip_addr *netmask,
struct ip_addr *gw,
err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif)) { // Start the TCP/IP thread & init stuff
tcpip_init(NULL, NULL);
// WARNING: This must only be run after the OS has been started.
// Typically this is the case, however, if not, you must place this
// in a post-OS initialization
return netifapi_netif_add(&my_netif, ipaddr, netmask, gw, NULL, init, input);
}
注:这个例子虽然假设使用静态IP,但是你可以将netif_set_up替换成dhcp_start或者autoip_start(详细请看Network interfaces management)
4.Network interfaces management
lwIP网络物理层的设备驱动被一个网络接口结构体所描述,与BSD很相似。网络接口保存在一个全局链表内,且被下一个指针所链接。
4.1 Starting a network interface
Step One: Add the interface
为了创建一个新的网络接口,用户 为结构体 netif分配内存空间(但是初始化它的任何部分),并调用netif_add:
struct *netif netif_add(struct netif *mynetif, struct ip_addr *ipaddr, struct ip_addr *netmask,
struct ip_addr *gw, void *state, err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, struct netif *netif));
用户指定一个IP地址,子网掩码和网关地址给该接口,这些值随后可以被改变
(1)state
State是一个特定于驱动的结构体,该结构体定义了许多其他”state”的必要信息来完成驱动的功能。
一些驱动会要求先设置state变量,然后再调用netif_add,但是很多时候要求这个参数为NULL。检查你的驱动可以获得更多信息
(2)init
init要求一个设备驱动初始化的函数,该函数一旦被调用netif结构体已经被netif_add准备好了。如果该驱动已经被初始化在你其它地方的代码,这个参数可以设为NULL
(3)input
当它接收到新的数据包时,参数input将会被一个驱动调用。这个参数将会需要如下一些函数:
ethernet_input
如果你不是在一个单线程环境中使用lwIP协议栈并且该驱动使用ARP(比如,以太网设备),则该驱动将会调用该函数来处理ARP数据包包括IP数据包。
ip_input
如果你不是在一个单线程环境中使用lwIP协议栈并且该接口并不是一个以太网设备,则该驱动会直接调用IP协议。
tcpip_ethinput
如果你使用tcpip应用线程(查看lwIP多线程),则该驱动将使用ARP,并且要定义lwIP的选项ETHARP_TCPIP_ETHINPUT。该函数将被驱动使用来将所有的IP和ARP数据包发给input函数
tcpip_input
如果你使用tcpip应用线程并且已经定义了ETHART_TCPIP_INPUT选项。则该函数被驱动使用来将IP数据包发给input函数。(驱动会分开ARP数据包并将它直接发送给ARP模块)。(注意:在lwip1.4.1里并没有tcpip_ethinput(),tcp_input将会处理所有的ARP数据包)
Step Two: Bring the interface up(打开接口)
一个接口如果是up状态,那么你的应用程序就可以使用该接口进行输入和输出,如果是down状态,则相反。因此,在使用该接口前,你一定要打开该接口(状态为up)。打开接口动作的完成取决于该接口如何得到IP地址。打开/关闭(up/dwon)函数对每种获得IP地址方式的区别如下所示:
n 静态IP地址:使用netif_set_up和netif_set_down。在你将接口打开前,你要确保已经设置了IP地址(通过netif_add或者netif_set_addr调用)。
n DHCP:使用dhcp_start和dhcp_stop。dhcp_start函数将会打开该接口,当它获得一个地址时设置IP地址。
n AUTOIP:使用autoip_start和autoip_stop。当它选中一个IP地址时,Autoip将会打开该接口并设置IP地址。
为了测试一个netif是否打开,你可以使用netif_is_up
4.2 Further netif
management
如果你加入一个netif接口,则该接口将会被当成默认的接口,于是你可以调用netif_set_default来确定默认的接口。当IP协议栈试图选择合适的路径(路由)来发送数据包时,如果该协议栈不能决定使用哪个正确的接口,那么它将通过默认的接口发送数据。如果你使用一个静态IP地址,那么你可以通过函数netif_set_ipaddr,netif_set_gw,和netif_set_netmask来设置该网络接口的相关的参数。当然你也可以使用netif_set_addr来一次设置这3个地址参数。当在文件lwipopts.h中设置LWIP_NETIF_STATUS_CALLBACK时,则该协议栈将提供一个状态回调函数。当接口打开或关闭时,则该状态回调函数将会被调用。举例,当你想要记录IP地址(该IP地址通过DHCP来获得)并想知道该地址的变化情况时,你就可以使用状态函数的钩子函数。设置一个netif接口的状态回调函数如下所示:
void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback);
LwIP Application Developers Manual11---Initializing lwIP的更多相关文章
- LwIP Application Developers Manual2---Protocols概览
1.前言 本文是对LwIP Application Developers Manual的翻译 lwIP是模块化的并支持广泛的协议,这些大部分协议可以被裁减从而减小代码的尺寸 2.协议概览 链路层和网络 ...
- LwIP Application Developers Manual1---介绍
1.前言 本文主要是对LwIP Application Developers Manual的翻译 2.读者(应用开发手册的读者) 谁适合读这份手册 网络应用的开发者 想了解lwIP的网络应用开发者 阅 ...
- LwIP Application Developers Manual5---高层协议之DHCP,AUTOIP,SNMP,PPP
1.前言 本文主要讲述高层协议,包括DHCP 2.DHCP 2.1 从应用的角度看DHCP 你必须确保在编译和链接时使能DHCP,可通过在文件lwipopts.h里面定义LWIP_DHCP选项,该选项 ...
- LwIP Application Developers Manual7---lwIP with or without an operating system
1.前言 最近有一些讨论关于lwIP如何在单机的环境(比如,没有一个多线程的操作系统)使用. 本文的目的就是描述lwIP如何在无多线程操作系统或有多线程操作系统环境中运行 2.lwIP单线程内核 2. ...
- LwIP Application Developers Manual9---LwIP and multithreading
1.前言 lwIP的内核并不是线程安全的.如果我们必须在多线程环境里使用lwIP,那么我们必须使用“upper”API层的函数(netconn或sockets).当使用raw API时,你需要自己保护 ...
- LwIP Application Developers Manual8---Sample lwIP applications
1.前言 你已经编译lwIP协议栈在你的目标平台上,并且网络驱动正常工作.你可以ping你的设备. 干得好,为你感到骄傲.虽然一个设备可以响应ping,但并不能算一个完整的应用. 现在你可以通过网络接 ...
- LwIP Application Developers Manual5---高层协议之DNS
1.前言 lwIP提供一个基本的DNS客户端(1.3.0后引进),通过使用DNS(Domain Name System)协议来允许应用程序解决主机名到地址的转换. 在文件lwipopts.h里面定义L ...
- LwIP Application Developers Manual4---传输层之UDP、TCP
1.前言 本文主要讲解传输层协议UDP TCP 2.UDP 2.1 UDP from an application perspective 2.2 UDP support history in lwI ...
- LwIP Application Developers Manual3---链路层和网络层协议之IPV6,ICMP,IGMP
1.前言 本文主要讲述链路层和网络层的协议IPV6,ICMP 2.IPV6 2.1 IPV6特性 IPv6是IPv4的更新.其最显著的差别在于地址空间由32位转换成128位 2.2 从应用的角度看IP ...
- LwIP Application Developers Manual12---Configuring lwIP
1.前言 2.LwIP makefiles With minimal features C_SOURCES = \ src/api/err.c \ src/core/init.c \ src/core ...
随机推荐
- 【JS】JavaScript中Null和undefind区别
1.undefined:只有一个值,及特殊的undefined.在使用var声明变量但未对其初始化时,这个变量的值是undefined,简言之,undefined就是表示变量申明了但未初始化时的值. ...
- I/O模型之四:Java 浅析I/O模型(BIO、NIO、AIO、Reactor、Proactor)
目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...
- 【1】[leetcode-124] 二叉树中的最大路径和
(没做出来,典型题目重要) 二叉树中的最大路径和(hard) 给定一个非空二叉树,返回其最大路径和. 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列.该路径至少包含一个节点,且不一定经 ...
- Docker 从入门到放弃(三)镜像使用
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载. 下面我们来学习: 1.管理和使用本地 Docker ...
- Jsp的四大作用域与九大对象
内置对象特点: 1. 由JSP规范提供,不用编写者实例化. 2. 通过Web容器实现和管理 3. 所有JSP页面均可使用 4. 只有在脚本元素的表达式或代码段中才可使用(<%=使用内置对象%&g ...
- vue实现简单日历
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C# using 的用法
Ø 前言 说起 C# using 语句,想必大家都不陌生,它是 C# 中关键字之一.我们基本每天写代码都会使用到,其实也非常简单. 1. 首先,说说 using 有哪些用途 1) 用于引用其 ...
- 关于TCP/IOCP构架中出现的Socket假死连接解决方案
如果在2台不同的公网机器,对TCP的c/s做过详细的压力测试,那么很不幸,会有很多人发现自己的server端会出现大量的假死连接. 假死连接具体表现如下: 1.在s端机器上,会有一些处于TCP_EST ...
- bean的装配方式(注入方式,构造注入,setter属性注入)
bean的装配方式有两种,构造注入和setter属性注入. public class User { private String username; private String password; ...
- Java SE之正则表达式四:获取
/** * * @author Zen Johnny * @date 2018年4月29日 下午4:51:08 * */ package demo.regex; import java.util.re ...