uip-中文说明

uip-中文说明
uip-中文说明

uIP 一个免费的TCP/IP栈

原文:Adam Dunkels

adam@https://www.360docs.net/doc/af11844320.html,

翻译:张伟林

okelinchang@https://www.360docs.net/doc/af11844320.html,

摘要

这个文档描述uIP TCP/IP栈。 uIP TCP/IP栈是使用于低至8位或16位微处理器的嵌入式系统的一个可实现的极小的TCP/IP协议栈。现时,uIP代码的大小和RAM的需求比其它一般的TCP/IP 栈要小。

uIP栈使用一个基于编程模块事件去减少代码的大小和RAM的使用量。基于系统的底层和uIP 之间的接口的回应会在文档里描述。系统的底层和uIP之间的接口是隐蔽的。文档后面包含了一些uIP应用编程例子。

uIP 的代码和这个文档的新版本可以在uIP的主页下载https://www.360docs.net/doc/af11844320.html,/adam/uip/。

这个文档描述了uIP的0.6版。

1 引言

新近这些年里,人们对连接一个甚至只是小装置到一个现有的IP网络例如全球因特网的兴趣增加了。为了可以通过因特网通讯,一个可实现的TCP/IP协议栈是必须的。uIP是一个可实现的TCP/IP协议组件的一个非常重要的部分。uIP的实现目标是保持代码大小和储存器使用量最小。现时,uIP代码的大小和RAM的需求比其它一般的TCP/IP栈要小。uIP使用C编程语言,它可以自用分发和使用于商业和非商业目的。

其它的TCP/IP栈,储存器经常用于数据缓存,等待一个数据已经成功送达的确应信号。事实上,数据包丢失了,数据必须重发。有特色的是,数据是缓存在RAM里,如果需要重发数据,应用程序可以快速重生数据。例如,一个HTTP服务器服务的大部分是ROM里的静态和半静态页,不需要在RAM里缓存静态内容。所以,如果一个包丢失了,HTTP服务器可以容易地从ROM里重生数据。数据简单地从原先的位置读回来。uIP的优越性是允许应用程序参加数据重发。

这个文档由以下部分组成,第2节描述在系统和应用的立场上怎样使用uIP。第3节详细讨论协议实现细节。第4 节覆盖了uIP的配置,第5节描述uIP的结构部分。最后,第6节提供一些uIP 的应用编程实例。

2 uIP的接口技术

uIP可以看作是一个代码库为系统提供确定的函数。图1 展示了uIP,系统底层和应用程序之间的关系。uIP提供三个函数到系统底层,uip_init(),uip_input(),和uip_periodic()。应用程序必须提供一个回应函数给uIP。当网络或定时事件发生时,调用回应函数。uIP提供许多函数和堆栈交互。

要注意的就是uIP提供的大部分函数是作为C的宏命令实现的,主要是为了速度,代码大小,效率和堆栈的使用。

图1 uIP就好像一个库

2.1 uIP应用接口

BSD套节字接口使用于大部分的操作系统,它不适合微系统,因为在应用设计里,它逼使一个线程基于编程模块。一个多线程环境代价重大,因为,不但在线程管理里涉及增加代码的复杂性,而且保存每线程堆栈需要额外的储存器,还有执行任务切换的时间开销也摊派在这里。微型系统不会有足够的资源去实现一个多线程环境,因此需要这个环境的应用接口不适合uIP。

相反,uIP使用一个基于编程模块的事件,模块是实现应用程序作为一个C函数被uIP调用的地方,uIP响应一定的事件。uIP调用应用在,当接收数据时,当数据成功送达另一方中止连接时,当一个新的连接建立时,或者当数据需要重发时。应用程序也周期性地循环等待新数据。应用程序只提供一个回应函数;它提升了应用程序处理不同的网络服务的不同的端口和连接的映射uIP与其它TCP/IP栈不同的是,当正在重发工作,它需要应用程序的帮助。其它TCP/IP栈缓存传输数据在储存器里,直到在连接的最后数据确应成功发送。如果数据需要重传,堆栈在没有通知应用程序下监视着重传工作。通过这种方法,当要等待一个确应,数据必须缓存在储存器里,如果产生一个重发,应用程序可以快速重新生成数据。为了减少储存器的使用量,uIP利用的论据是应用程序可以重新生成发送的数据和让应用程序参加重发。

2.1.1 uIP应用事件

应用程序必须作为C函数去实现,uIP在任何一个事件发生时调用UIP_APPCALL()。表 1 列出可能的事件和每个事件的对应测试函数。测试函数用于区别不同的事件。函数是作为C宏命令实现的,将会是零值或非零值。注意的是某些函数可以在互相连接时发生(也就是新数据可以在数据确应的同时到达)。

表1: uIP应用事件和对应的测试参数

一个数据包到达,确应先前发送到数据uip_acked()

应用程序的新数据包已经到达uip_newdata()

一个远程主机连接到监听端口uip_connected()

一个到达远程主机的连接成功建立uip_connected()

计时时间满重发uip_rexmit()

计时时间满周期性轮询uip_poll()

远程主机关闭连接uip_closed()

远程主机中断连接uip_aborted()

由于太多重传,连接中断uip_timedout()当应用程序调用时,uIP设置全局变量uip_conn去指向当前连接的uip_conn结构(图5) 。这可以用来区别不同的服务。一个典型的应用是检查uip_conn->lport (当地TCP端口号)去决定那个

服务连接应该提供。例如,如果值uip_conn->lport等于80,应用程序可以决定启动一个HTTP服务,值是23是启动TELNET服务。

2.1.2 接收数据

如果uIP测试函数uip_newdata()值为1,远程连接的主机有发送新数据。uip_appdata指针指向实际数据。数据的大小通过uIP函数uip_datalen()获得。在数据不是被缓冲后,应用程序必须立刻启动。

2.1.3 发送数据

应用程序通过使用uIP函数uip_send()发送数据。uip_send()函数采用两个参数;一个指针指向发送数据和数据的长度。如果应用程序为了产生要发送的实际数据需要RAM空间,包缓存(通过uip_appdata指针指向)可以用于这方面。

在一个时间里应用程序只能在连接中发送一块数据。因此不可以在每个应用程序启用中调用uip_send()超过一次;只有上一次调用的数据将会发出后才可以。注意,调用uip_send()以后会改变某些全局变量,在应用函数返回前它不能被调用。

2.1.4 重发数据

如果数据在网络中丢失,应用程序必须重发数据。无论数据收到或没有收到,uIP保持跟踪,和通知应用程序什么时候察觉出数据是丢失了。如果测试函数uip_rexmit()为真,应用程序要重发上一次发出的数据。重发就好像原来那样发送,也就是通过uip_send()。

2.1.5 关闭连接

应用程序通过调用uip_close()关闭当前连接。这会导致连接干净地关闭。为了指出致命的错误,应用程序可以中止连接和调用uip_abort()函数完成这个工作。

如果连接已经被远端关闭,测试函数uip_closed()为真。应用程序接着可以做一些必要的清理工作。

2.1.6 报告错误

有两个致命的错误可以发生在连接中,不是连接由远程主机中止,就是连接多次重发上一数据和被中止。uIP通过调用函数报告这些问题。应用程序使用两个测试函数uip_aborted()和uip

_timedout() 去测试那些错误情况。

2.1.7 轮询

当连接空闲时,uIP在每一个时候周期性地轮询应用程序。应用程序使用测试函数uip_poll()去检查它是否被轮询过。

2.1.8 监听端口

uIP维持一个监听TCP端口列表。通过uip_listen()函数,一个新的监听端口打开。当一个连接请求在一个监听端口到达,uIP产生一个新的连接和调用应用程序函数。如果一个新连接产生,应用程序被调用,测试函数uip_connected()为真。

2.1.9 打开连接

作为uIP的0.6版,在uIP里面通过使用uip_connect()函数打开一个新连接。这个函数打开一个新连接到指定的IP地址和端口,返回一个新连接的指针到uip_conn结构。如果没有空余的连接槽,函数返回空值。为了方便,函数uip_ipaddr()可以用于将IP地址打包进两个单元16位数组里,通过uIP去代表IP地址。

使用两个例子,在图 2 和图 3 展示。第一个例子展示了怎样打开一个连接去远端TCP端口8080。如果没有足够的TCP连接插槽去允许一个新连接打开,uip_connect()函数返回NULL和通过uip_abort()中止当前连接。第二个例子展示怎样打开一个新连接去指定的IP地址。这例子里没有错误检查。

void connect_example1_app(void) {

if(uip_connect(uip_conn->ripaddr, 8080) == NULL) {

uip_abort();

}

}

图2:打开一个连接去当前连接的远端的端口8080

void connect_example2(void) {

u16_t ipaddr[2];

uip_ipaddr(ipaddr, 192,168,0,1);

uip_connect(ipaddr, 8080);

}

图3: 打开一个到主机192.168.0.1上端口8080的连接

2.1.10 数据流控制

通过函数uip_stop()和uip_restart(),uIP提供存取TCP数据流的控制途径。设想一个应用程序下载数据到一个慢速设备,例如磁盘驱动器。如果磁盘驱动器的作业队列满了,应用程序不会准备从服务器接收更多的数据,直到队列排出空位。函数uip_stop()可以用于维护流控制和停止远程主机发送数据。当应用程序准备好接收更多数据,函数uip_restart()用于告知远程终端再次发送数据。函数uip_stopped()可以用于检查当前连接是否停止。

2.2 uIP/系统接口

从系统的立场看,uIP由3个C函数uip_init(),uip_input(), 和uip_periodic()。uip_init()函数用于初始化uIP堆栈和在系统启动期间调用。当网络设备驱动器读一个IP包到包缓存时,调用函数uip_input()。周期性运行是调用uip_periodic(),代表的是一秒一次。调用uIP函数是系统的职责。

2.2.1 uIP/设备驱动接口

当设备驱动放一个输入包在包缓存里(uip_buf),系统应该调用uip_input()函数。函数将会处理这个包和需要时调用应用程序。当uip_input()返回,一个输出包放在包缓存里。包的大小由全局变量uip_len约束。如果uip_len是0,没有包要发送。

2.2.2 uIP/周期计时接口

周期计时是用于驱动所有uIP内部时钟事件,例如包重发。当周期计时激发,每一个TCP连接应该调用uIP函数uip_periodic()。连接编号传递是作为自变量给uip_periodic()函数的。类似于uip_input()函数,当uip_periodic()函数返回,输出的IP包要放在包缓存里。图4 展示了调用

uip_periodic()函数和监视输出包的一小段代码。在这个特别的例子,函数netdev_send()是网络驱动的部分,将uip_buf数组的目录发出到网上。

for(i = 0; i < UIP_CONNS; ++i) {

uip_periodic(i);

if(uip_len > 0)

netdev_send();

}

图4:周期计时和uIP的接口的例子代码.

2.3 uIP 函数总结

表2包含了所有uIP提供的函数

表2: uIP 函数总结

系统接口

uip_init()

uip_input() uip_periodic() 初始化uIP

处理输入包

处理周期计时事件

应用程序接口

uip_listen() uip_connect() uip_send() uip_datalen() uip_close() uip_abort() uip_stop() uip_stopped() uip_restart() 开始监听端口

连接到远程主机

在当前连接发送数据输入数据的大小

关闭当前连接

中止当前连接

停止当前连接

查找连接是否停止重新启动当前连接

测试函数

uip_newdata() uip_acked()

uip_connected() uip_closed() uip_aborted() uip_timeou() uip_rexmit

uip_poll() 远程主机已经发出数据确应发出的数据

当前连接刚连上

当前连接刚关闭

当前连接刚中止

当前连接刚超时

数据重发

应用程序循环运行

其它

uip_mss()

uip_ipaddr() htons(),ntohs() 获得当前连接的最大的段大小将IP地址结构打包

在主机和网络之间转换字节次序

3 实现协议

uIP实现了TCP/IP协议组的四个基本协议;ARP [Plu82],IP [Pos81b], ICMP [Pos81a] 和TCP [Pos81c]。链路层协议例如PPP可以实现作为uIP下面的设备驱动。应用层协议例如HTTP, FTP 或SMTP可以实现为uIP之上的应用程序。

3.1 地址解析协议| ARP

ARP协议映射了IP地址和以太网MAC物理地址,它在以太网上的TCP/IP操作是需要的。ARP 在uIP里实现的是包含一个IP到MAC地址的映射。当一个IP包要在以太网上发出,查询ARP表,去找出包要发送去的MAC地址。如果在表里找不到IP地址,ARP请求包就会发出。请求包在网络里广播和请求给出IP地址的MAC地址。主机通过发出一个ARP回应,响应请求IP地址。当uIP 给出一个ARP回应,更新ARP表。

为了节省储存器,一个IP地址的ARP请求覆盖发出的请求输出IP包。它是假定上层将重新发送那些被覆盖了的数据。

每十秒表更新一次,旧的条目会被丢弃。默认的ARP表条目生存时间是20分钟。

3.2 网际协议| IP

uIP的IP层代码有两个职责:验证输入包的IP头的正确性和ICMP 和TCP协议之间多路复用。IP层代码是非常简单的,由9条语句组成。事实上,uIP的IP层极大地简化了,它没有实现碎片和重组。

3.3 因特网信息控制协议| ICMP

在uIP里,只有一种ICMP信息实现了:ICMP回响信息。ICMP回响信息常常用于ping程序里

的检查主机是否在线。在uIP里,ICMP回响处理在一个非常简单的方式。ICMP类型字段的改变是从\echo"类型到\echo reply"类型,从而ICMP调整校验和。其次,IP地址里的IP头交换,包发回到原先的发送者。

3.4 传输控制协议| TCP

为了减少储存器的使用,uIP里的TCP没有实现发送和接收数据的调整窗口。输入的TCP段不会通过uIP缓存,但必须立即由应用程序处理。注意这不能避免应用程序自己缓冲数据。输出数据时,uIP不能在每个连接有超过一个未解决的TCP段。

3.4.1 连接状态

在uIP,每个TCP连接的完全态包含当地和远端的TCP端口编号,远程主机的IP地址,重发时间值,上一段重发的编号,和连接的段的最大尺寸。除此之外,每个连接也可以保持一些应用状态。三个序列号是,期望接收的下一个字节的序列号,上一发送段第一字节的序列号,下一发送字节的序列号。连接的状态由uip_conn结构表现,可以在图5看到。一个uip_conn结构数组用于在uIP里保持所有的连接。数组的大小等于同时的最大数量的连接,它在编译时间里设置(看第 4 节)。

struct uip_conn {

u8_t tcpstateflags; /* TCP状态和标志. */

u16_t lport, rport; /*当地和远端端口. */

u16_t ripaddr[2]; /*同等远端的IP地址. */

u8_t rcv_nxt[4]; /* 我们期待接收的下一个序列号. */

u8_t snd_nxt[4]; /*上一个发送的序列号. */

u8_t ack_nxt[4]; /* 通过从远端的下一个应答去应答序列号. */

u8_t timer; /* 重发时间r. */

u8_t nrtx; /*计算特殊段的重发数量. */

u8_t mss; /* 连接的最大段大小. */

u8_t appstate[UIP_APPSTATE_SIZE];

};

图5: uip_conn 结构

3.4.2输入处理

TCP输入处理和检验TCP校验和一起开始。如果校验和是对的,在当前活动的TCP连接之间,源、目的端口号和IP地址复用包。没有活动的连接符合输入包时,如果包不是一个监听端口的连接请求,包丢弃。如果包是一个关闭端口的请求,uIP 发一个RST包回应。

如果发现了一个监听端口,uip_conn结构数组扫描任何一个非活动连接。如果发现一个,数组由新连接的端口号和IP地址填充。如果连接请求携带一个TCP MSS (最大段大小)选择,它会分析,再次检查当前最大段大小MSS去决定当前连接的MSS,前后者的最小值会被选择。最后,一个回应包发去确应开启连接。

应该将输入包送去一个已经活跃的连接,包的序列号和从远端主机来的期望的下一个序列号一起被检查(uip_conn结构里的rcv_nxt 变量显示于图5)。如果序列号不是期望得到的下一个,包会被丢掉和发一个ACK去指出期望得到的下一个序列号。紧接着,检查输入包里的确应号,看看是否确应连接的所有输出数据。它做了后,应用程序会知道这个事实的。

当序列号和确应号被检测过,依靠当前TCP状态,包将会被不同地处理。如果连接在

SYN-RCVD状态和输入包确应先前发送的SYNACK包,连接将会输入ESTABLISHED状态,调用应用函数去通知已经完全连接。在连接的建立状态,如果有新数据由远端主机发送或者远端主机确应之前发送的数据,就调用应用函数。

当应用函数返回,TCP检查应用程序是否还有数据要发。如果有,一个TCP/IP包会形成在包

缓存里。

3.4.3 输出处理

输出处理过程比输入处理直接和简单得多。基本上,所有TCP和IP头字段由uip_conn 结构里的值充满,计算TCP和IP的校验和。当uip_process()函数返回,包通过网络设备驱动发出去。

3.4.4 重发

当uIP通过periodic_timer被调用时,重发就进入运作(看段 2.2.2)。连接里有些特殊的数据(也就是数据发出了去但仍没有确应的)通过UIP_OUTSTANDING位在uip_conn 结构里的TCP状态标志变量标记(图5)。那个连接,时间变量减少。当时间到达零,上一段必须重发和调用应用函数去做真正的重发。如果一个特殊段重发编号超出一个可设置的界限,连接会结束和发一个RST 段到远端连接结束,调用应用函数去通知它连接超时。

3.4.5 重置TCP

TCP规格要求如果TCP头里的序列号和确应号在当前连接的接收窗口失去了,有RST (复位)标志设置的包必须断开连接。为了减少代码的大小,uIP不严格遵守这个规定。相反,如果一个有RST标志设置的包在连接里到达,连接会消灭那些不重要的序列号和确应号值。这个行为将会在将来的uIP版本修订。

4 配置uIP

uIP的设置隐藏在一个叫uipopt.h的单独头文件里。这个文档不及包含了那些项目特性的设置选项(例如uIP网点的IP地址和同时发生连接的最大值),而且有结构和C编译器的特殊选项。文档是独立的和有注释说明的。

5 构做具体函数

当IP,ICMP和TCP协议在单一的C函数里实现(uip_process()函数),它们需要四个支持函数的帮助。支持函数实现32位添加和计算校验和。在uIP的0.4版本,支持函数的实现由实际的协议拆分,这是为了易于手工将支持函数汇编。在支持函数频繁被调用后,有实际的增益是使那些函数运行得越来越快

四个支持函数中有两个是计算IP和TCP校验和,uip_ ipchksum(),uip_tcpchksum(),另两个是执行TCP序列号的32位添加:uip_add_ack_nxt()和uip_add_rcv_nxt()。uIP分类包括简单的支持函数C实现。

uip_ipchksum()计算和返回网间IP头的校验和[BBP88],但没有进行检验和的位非操作。IP头可以在uip_buf数组的头20字节找到。

uip_tcpchksum()函数计算TCP校验和。TCP校验和是TCP头和数据的网间校验。这个函数事实上有点复杂,TCP头和TCP数据可以在不同的储存器位置找到。在uip_buf数组开头可以找到TCP头的20字节(也就是在&uip_buf[20]) ,uip_appdata指针指向TCP数据的开头。TCP数据的大小可以通过从整个包中减去IP和TCP头得出。包的大小包含在uip_len这个全局变量里。因为uIP 不支持数据流里的IP或者TCP选择,IP和TCP头的大小是40字节。

6 应用例子

这节提供一些简单的uIP应用例子

6.1 一个简单的应用例子

第一个例子非常简单。应用程序监听输入连接的端口1234。当一个连接建立了,应用程序通过说“OK”回应所有发送给它的数据。

图 6 显示了应用程序的实现。应用程序调用example1_init()初始化,uIP的回叫函数是example1_app(),在这个例子里,可设置的变量UIP_APPCALL应该要定义在example1_app。

初始化函数调用uIP函数uip_listen()去注册一个监听端口。实际的应用函数example1_app()使用测试函数uip _newdata()和uip_rexmit()去确定为什么调用它。如果调用应用程序是因为最远端发了数据给它,它回应一个"ok"。如果调用应用函数是因为数据在网络里丢失和需要重发,它也发送一个"ok"。

注意,这个例子显示了一个完全的uIP应用。应用程序不需要处理所有类型事件例如:

uip _connected()或uip_timedout()。

void example1_init(void) {

uip_listen(1234);

}

void example1_app(void) {

if(uip_newdata() || uip_rexmit()) {

uip_send("ok\n", 3);

}

}

图6: 一个非常简单的应用程序

6.2 一个更高级的应用

第二个例子只是稍微比第一个高级一点,显示了程序中状态段怎样在uip_conn结构中使用。

这个应用程序和第一有些相似,它监听一个输入连接的端口和回应发送给它的数据一个"ok"。最大的不同是当连接建立时,这个程序打印输出一个欢迎信息"Welcome!"。

程序怎样实现,表面上是操作上的小改动产生效果上很大的不同。复杂性增加的原因是如果数据在网络里丢失,程序必须知道那个数据需要重发。如果"Welcome!"信息丢失了,程序必须重发欢迎信息,如果其中一个"ok"信息丢失,程序必须发一个新的"ok"。

程序知道只要"Welcome!"信息没有被远程主机确应,它就可能在网络里丢失了。但一旦远程主机已发了一个确应回来,程序可以应为欢迎信息已经被接收,知道一些丢失的数据是一个"ok"信息。因此程序可以在两个之中的一个状态:在WELCOME-SENT状态,"Welcome!"已经发出但没有被确应,或者WELCOME-ACKED状态,"Welcome!"已被确应。

当远程主机连接到应用程序时,程序发一个"Welcome!"信息和发它的状态去

WELCOME-SENT。当欢迎信息被确应了,程序进入WELCOME-ACKED状态。如果程序从远程主机收到任何新数据,它回应一个"ok" 。

如果应用程序被请求重发上一条信息,它看程序在那个状态。如果程序在WELCOME-SENT 状态,它知道先前的欢迎信息没有被确应,它再发一个"Welcome!"信息。如果程序在WELCOME-ACKED状态,它知道上一条信息是"ok" ,只发一条信息。

应用的实现可以在图7看到。图8显示了应用的设置

struct example2_state {

enum {WELCOME_SENT, WELCOME_ACKED} state;

};

void example2_init(void) {

uip_listen(2345);

}

void example2_app(void) {

struct example2_state *s;

s = (struct example2_state *)uip_conn->appstate;

if(uip_connected()) {

s->state = WELCOME_SENT;

uip_send("Welcome!\n", 9);

return;

}

if(uip_acked() && s->state == WELCOME_SENT) {

s->state = WELCOME_ACKED;

}

if(uip_newdata()) {

uip_send("ok\n", 3);

}

if(uip_rexmit()) {

switch(s->state) {

case WELCOME_SENT:

uip_send("Welcome!\n", 9);

break;

case WELCOME_ACKED:

uip_send("ok\n", 3);

break;

}

}

}

图7: 一个高级应用

#define UIP_APPCALL example2_app

#define UIP_APPSTATE_SIZE sizeof(struct example2_state)

图8: 应用程序设置

6.3 区分应用程序

如果系统要运行多个应用程序,区分它们的其中一个技术是使用连接的远程终端或当地终端的TCP端口编号。图9 显示了怎样将上面的例子结合在一个应用程序里。

void example3_init(void) {

example1_init();

example2_init();

}

void example3_app(void) {

switch(uip_conn->lport) {

case htons(1234):

example1_app();

break;

case htons(2345):

example2_app();

break;

}

}

图9: 两个应用程序组合和使用不同的当地端口

6.4 接收大量数据

这个例子显示了一个简单的程序连接去主机,发一个文件的HTTP请求和从慢速设备如磁盘

驱动器下载文件。这个显示了怎样使用uIP的流控制函数。程序显示在图10。

当连接已经建立,一个HTTP请求发去服务器。这是唯一的发送数据,应用程序知道是否需要重发数据,那么请求要重发。所以要合理的将两个事件结合在例子里。

当应用程序从远程主机接收数据,它通过使用函数device_enqueue()发这些数据去设备。要注意的是这个例子假设这个函数复制数据去它自己的缓存。在uip_appdata缓存的数据将会被下一个输入数据覆盖。

如果等待设备的队列满了,应用程序通过调用uIP函数uip_stop()停止来之远程主机的数据。应用程序确保它不接收任何数据,直到调用uip_restart()。应用程序轮询事件,用于检查队列是否不在满,如果没满,通过uip_restart()数据流重新开始。

void example4_init(void) {

u16_t ipaddr[2];

uip_ipaddr(ipaddr, 192,168,0,1);

uip_conn(ipaddr, 80);

}

void example4_app(void) {

if(uip_connected() || uip_rexmit()) {

uip_send("GET /file HTTP/1.0\r\nServer:192.186.0.1\r\n\r\n",48);

return;

}

if(uip_newdata()) {

device_enqueue(uip_appdata, uip_datalen());

if(device_queue_full()) {

uip_stop();

}

}

if(uip_poll() && uip_stopped()) {

if(!device_queue_full()) {

uip_restart();

}

}

}

图10: 一个接收大量数据的应用程序

6.5 一个简单的网络服务器

这个例子显示了一个非常简单的文件服务器程序和使用端口编号去决定发送那个文档。如果文档适当格式化一下,这个简单的程序可以作为一个有静态网页的网络服务器。图11 显示了实现方法。

应用程序的状态包括一个指向要发送数据的指针和剩下发送数据的大小。当一个远程主机连接去应用程序,当地端口编号用于决定那个文档要发送。第一块数据使用uip_send()发送。由于有监管,至多的最大段字节数据发送了。

应用程序由肯定应答驱动。当数据被确应,新数据可以发送。如果没有数据要发送了,连接使用uip_close()关闭。

struct example5_state {

char *adaptor;

unsigned int dataleft;

};

void example5_init(void) {

uip_listen(80);

uip_listen(81);

}

void example5_app(void) {

struct example5_state *s;

s = (struct example5_state)uip_conn->appstate;

if(uip_connected()) {

switch(uip_conn->lport) {

case htons(80):

s->dataptr = data_port_80;

s->dataleft = datalen_port_80;

break;

case htons(81):

s->dataptr = data_port_81;

s->dataleft = datalen_port_81;

break;

}

uip_send(s->dataptr , uip_mss() < s->dataleft? uip_mss(): s->dataleft);

return;

}

if(uip_acked()) {

if(s->dataleft < uip_mss()) {

uip_close();

return;

}

s->dataptr += uip_mss();

s->dataleft -= uip_mss();

uip_send(s->dataptr , uip_mss() < s->dataleft? uip_mss(): s->dataleft);

}

}

图11: 一个简单的文件服务器

参考

[BBP88] R. Braden, D. Borman, and C. Partridge. Computing the internet checksum. RFC 1071, Internet Engineering Task Force, September 1988.

[Plu82] D. C. Plummer. An ethernet address resolution protocol. RFC 826,Internet Engineering Task Force, November 1982.

[Pos81a] J. Postel. Internet control message protocol. RFC 792, Internet Engineering Task Force, September 1981.

[Pos81b] J. Postel. Internet protocol. RFC 791, Internet Engineering Task Force, September 1981. [Pos81c] J. Postel. Transmission control protocol. RFC 793, Internet Engineering Task Force, September 1981.

uIP的ARP协议代码分析之二 ARP应答

ARP应答部分代码为uip_arp.c中的void uip_arp_arpin(void)函数. 这个函数是在设备接收到ARP包时,由驱动程序调用的. 如果收到是ARP包是一个对本地主机上次发送的ARP请求的应答,那么就从包中取得自己想要的主机的MAC地址,加入自己的ARP缓存表中. 如果收到是一个ARP请求,那就把自己的MAC地址打包成一个ARP应答,发送给请求的主机. 看代码uip_arp.c的254行: 1./*----------------------------------------------------------------- ------------------*/ 2./** 3.* ARP processing for incoming ARP packets. 4.*对传入的ARP包的处理. 5.* This function should be called by the device driver when an ARP 6.* packet has been received. The function will act differently 7.* depending on the ARP packet type: if it is a reply for a request 8.* that we previously sent out, the ARP cache will be filled in with 9.* the values from the ARP reply. If the incoming ARP packet is an ARP 10.* request for our IP address, an ARP reply packet is created and put 11.* into the uip_buf[] buffer. 12.*此函数在收到ARP包时由设备驱动调用,函数行为会因包类型而有不同.如果 收到的是一个对前先发送的请求的应答 13.*则根据应答的值填充缓存.如果传入的包是对我们的IP的请求,则创建一个 ARP应答,并放入uip_buf[]中. 14.* When the function returns, the value of the global variable uip_len 15.* indicates whether the device driver should send out a packet or 16.* not. If uip_len is zero, no packet should be sent. If uip_len is 17.* non-zero, it contains the length of the outbound packet that is 18.* present in the uip_buf[] buffer. 19.*函数返回时,全局变量uip_len的值指明了设备驱动要不要发送包.若 uip_len为0,则不需发送,若uip_len不是0, 20.* 则其值是uip_buf[]中包含的要传出的包的大小. 21.* This function expects an ARP packet with a prepended Ethernet 22.* header in the uip_buf[] buffer, and the length of the packet in the 23.* global variable uip_len.此函数预期中的uip_buf中有一个带以太网头的 ARP包.其长度存为uip_len中. 24.*/ 25./*----------------------------------------------------------------- ------------------*/ 26.void 27.uip_arp_arpin(void) 28.{ 29. 30.if(uip_len < sizeof(struct arp_hdr)) { 31.uip_len = 0;

以太网及TCPIP通俗理解

1 以太网------EtherNet: ---------------------------参考图解 以太网最早由Xerox(施乐)公司创建,于1980年DEC、lntel和Xerox三家公司联合开发成为一个标准。以太网是应用最为广泛的局域网,包括标准的以太网(10Mbit/s)、快速以太网(100Mbit/s)和10G(10Gbit/s)以太网,采用的是CSMA/CD访问控制法,它们都符合IEEE802.3。 IEEE 802.3标准 IEEE802.3规定了包括物理层的连线、电信号和介质访问层协议的内容。以太网是当前应用最普遍的局域网技术,它很大程度上取代了其他局域网标准。如令牌环、FDDI和ARCNET。历经100M以太网在上世纪末的飞速发展后,目前千兆以太网甚至10G以太网正在国际组织和领导企业的推动下不断拓展应用范围。 常见的802.3应用为: 10M: 10base-T (铜线UTP模式) 100M: 100base-TX (铜线UTP模式) 100base-FX(光纤线) 1000M: 1000base-T(铜线UTP模式) 2 UIP协议: uIP由瑞典计算机科学学院(网络嵌入式系统小组)的Adam Dunkels 开发。其源代码由C 语言编写,并完全公开,uIP 的最新版本是1.0 版本,本指南移植和使用的版本正是此版本。uIP协议栈去掉了完整的TCP/IP中不常用的功能,简化了通讯流程,但保留了网络通信 必须使用的协议,设计重点放在了IP/TCP/ICMP/UDP/ARP这些网络层和传输层协议上,保证了其代码的通用性和结构的稳定性。 由于uIP协议栈专门为嵌入式系统而设计,因此还具有如下优越功能: 1)代码非常少,其协议栈代码不到6K,很方便阅读和移植。 2)占用的内存数非常少,RAM 占用仅几百字节。 3)其硬件处理层、协议栈层和应用层共用一个全局缓存区,不存在数据的拷贝,且发送和接收都是依靠这个缓存区,极大的节省空间和时间。 4)支持多个主动连接和被动连接并发。 5)其源代码中提供一套实例程序:web 服务器,web 客户端,电子邮件发送程序(SMTP 客户端),Telnet服务器,DNS主机名解析程序等。通用性强,移植起来基本不用修改就可以通过。 6)对数据的处理采用轮循机制,不需要操作系统的支持。 由于uIP对资源的需求少和移植容易,大部分的8位微控制器都使用过uIP 协议栈,而且很多的著名的嵌入式产品和项目(如卫星,Cisco 路由器,无线传感器网络)中都在使用uIP 协议栈。 3 TCP/IP协议: TCP/IP是(Transmission Control Protocol/Internet Protocol)的简写,中译名为传输控制协

TCPIP协议规范及UIP处理流程模板

TCPIP协议规范及UIP处 理流程模板 目录 一、简要历史 (4) 二、TCP/IP协议族 (4) 2.1. 简介 (4) 2.2. 编址 (5) 2.2.1 物理地址 (5) 2.2.2 逻辑地址 (5) 2.2.3 端口地址 (8) 2.3. 分层数据包介绍 (8) 2.3.1 以太网帧 (8) 2.3.2 ARP报文格式 (9)

2.3.3 IP数据报格式 (11) 23.4 ICMP报文格式 (13) 2.3.5 IGMP报文格式 (15) 23.6 UDP用户数据报首部格式 (16) 2.3.7 TCP报文段格式 (17) 2.4. 分层协议讲解 (19) 2.4.1 ARP 和RARP (20) 2.4.2 IP 协议 (23) 2.4.3 ICMP 协议 (25) 2.4.4 网际组管理协议(IGMP) (30) 2.4.5 用户数据报(UDP) (31) 2.4.6 传输控制协议(TCP) (34) 三、UIP处理流程 (40) 3.1. 简介 (40) 3.2. 层次结构 (41) 3.2.1 实现设备驱动与UIP对接需要的7个接口程序,定义在uip.h: (42) 3.2.2 应用层要调用的函数,包括一些宏定义与函数,定义在uip.h: (48) 3.2.3 UIP中所用到的主要结构体 (55) 3.2.4 uip的初始化与配置函数 (64) 3.2.5 Uip的主程序循环 (67) 3.2.6 主要的处理函数uip_process() (71) 3.2.7 再來分析UIP_UDP_SEND_CONN,主要处理UDP报文的发送: (79) 3.2.8 接下來,分析UIP_POLL_REQUEST (82) 3.2.9 对定时器期满的处理流程UIP_TIMER (84) 3.2.10 对UIP_UDP_TIMER 的处理流程 (86) 3.2.11 原始套接字和原始线程 (87)

2012.11.6战略智慧笔记 陈果

N 《战略智慧》 --陈果 如何建立战略思维? 你现在最需要解决的是什么问题? 1、未来老百姓的健康生活方式? 2、房产中介的人力资源 3、企业做到一定程度,如何把规模缩小? 4、如何使用90后? 5、外贸出口利润越来越低,公司成本越来越大,如何突破?需要经营的: 1、原始积累(财富) 2、内部团队(精神共同体) 团队是利润,是巨大财富 3、忠实客户(了解客户需求) 企业一定要战略升级,为谁请命? 老板需要经营“空手套白狼”的本领。 企业做大的因素: 1、政府的力量 2、资金对你的加持 3、消费者对你的关注 4、优秀的人才向你靠齐

利润 (如:外婆家) 如:宋城集团,通过做“宋城千古情”项目,获得政府的支持 大老板:看似很傻,实际很厉害,用一年的时间赚10年的钱 如:王志纲老师用三十年的时间做中国最好的“战略思想智库”,一转身获得无数的财富 经营企业就是经营人,经营企业就是经营价值。 企业、产品都是媒介,关键是你想到哪里去。 战略思维思考的问题是:我要到哪里去? 老板必须为战略负责! 战略是唯一不能让职业经理人去做的事情。 没有战略就没有人追随,如果成功也是偶然的。 如:王建林(万达集团),当初做商业地产,所有人都反对如:吴亚军,(南湖地产,温州人)当初做战略十几人的核心团队全部走掉,但今天成为中国女首富。 老板不是所有事情都需要你来做,而是那些事情是你必须要做的。

如:华为,力排众议做最适合当下的战略 这是一场越来越激烈的商战,不要妄想今天的困难明天就过去了,要有打战的思维 如:微软 在战争当中总结经验,这是老板需要修炼的 战略智慧金三角: 找定位 定打法 开模具 战略之道的根本是定位。 打法和模具的关系: 模具是企业超级杀伤力的武器 如:工作室:帮企业找魂,帮企业开模具书院班:帮企业开模具,寻找战略突破打法:合适的发射装置 打法与模具的关系是炮弹和炮筒的关系 孵化人的板块: 从老板到老师的智慧

uip移植笔记

本笔记适用于uIP1.0。 移植平台介绍:MSP430F149+cs8900a+IAR 1、阅读The uIP Embedded TCP/IP Stack The uIP 1.0 Reference Manual. 2、建立一个文件夹,起名myport,将uip-1.0下的uIP和lib两个文件夹拷贝过去,然后再在myport下建立app文件夹。 3、将unix子文件夹下的clock-arch.c、clock-arch.h拷贝到myport下,这个文件实现协议栈所用的时钟,由430的定时器完成,有三个函数: clock_time_t clock_time(void) { return ticks; } void clock_init(void) { 定时器的初始化工作 } __interrupt void timer_interrupt(void)/*定时器中断函数*/ { ++ticks; }。 4、将unix子文件夹下的uip-conf.h拷贝到myport下,这个文件实现协议栈所用的配置,按照需要修改之。 5、写cs8900a的驱动函数,这里采用8位、查询模式,替换tapdev.c 或slipdev.c。 6、将unix子文件夹下的main.c函数拷贝到myport下,这个是主调度流程,按照需要修改。 7、建立自己的工程,将以上文件包含。 8、调试,改错。 其中,uip的缓冲区是以字节数组的形式产生,为了保证它的起始地址是偶数,必须指定地址。 UDP的初始化如下 void myudp_init(void) { uip_ipaddr_t ipaddr;//定义IP类型变量 uip_ipaddr(ipaddr, 210,29,104,88); //远程IP为210.29.104.88 if(myudp_conn != NULL) { uip_udp_remove(myudp_conn);//如果连接已经建立,则删除之 } myudp_conn = uip_udp_new(&ipaddr, HTONS(1000));//建立到远程ipaddr,端口为1000的连接 if(myudp_conn != NULL) {

uip协议栈

uIP协议栈分析 uIP特性 uIP协议栈往掉了完整的TCP/IP中不常用的功能,简化了通讯流程,但保存了网络通讯必须使用的协议,设计重点放在了IP/TCP/ICMP/UDP/ARP这些网络层和传输层协议上,保证了其代码的通用性和结构的稳定性。 由于uIP协议栈专门为嵌进式系统而设计,因此还具有如下优越功能: (1)代码非常少,其协议栈代码不到6K,很方便阅读和移植。 (2)占用的内存数非常少,RAM占用仅几百字节。 (3)其硬件处理层、协议栈层和应用层共用一个全局缓存区,不存在数据的拷贝,且发送和接收都是依靠这个缓存区,极大的节省空间和时间。 (4)支持多个主动连接和被动连接并发。 (5)其源代码中提供一套实例程序:web服务器,web客户端,电子邮件发送程序(SMTP 客户端),Telnet服务器,DNS主机名解析程序等。通用性强,移植起来基本不用修改就可以通过。 (6)对数据的处理采用轮循机制,不需要操纵系统的支持。 由于uIP对资源的需求少和移植轻易,大部分的8位微控制器都使用过uIP协议栈, 而且很多的著名的嵌进式产品和项目(如卫星,Cisco路由器,无线传感器网络)中都在使用uIP协议栈。 uIP架构 uIP相当于一个代码库,通过一系列的函数实现与底层硬件和高层应用程序的通讯,对于整个系统来说它内部的协议组是透明的,从而增加了协议的通用性。uIP协议栈与系统底层和高层应用之间的关系如图2-1所示。 从上图可以看出,uIP协议栈主要提供了三个函数供系统底层调用。即uip_init(), uip_input() 和uip_periodic()。其与应用程序的主要接口是UIP_APPCALL( )。 uip_init()是系统初始化时调用的,主要初始化协议栈的侦听端口和默认所有连接是封闭的。当网卡驱动收到一个输进包时,将放进全局缓冲区uip_buf中,包的大小由全局变量uip_len

ucos操作系统在ARM上的移植

UC/OS-II 嵌入式系统在ARM 上的移植 UC/OS-II 操作系统是一款完全公开的源代码,它非常精简,整个操作系统的代码只有几千行,是专门针对于嵌入式开发而产生的一款代码。它有几个特点,分别是可移植性(Portable )、可固化(ROMable )、可裁剪(Scalable )、多任务、可确定性、任务栈、系统服务、中断管理、稳定性可靠性。 UC/OS-II 主要就是一个内核,由ANSIC 语言编写而成。负责任务管理和任务调度,没有文件系统和界面系统。它的代码是公开的,系统的实时性强、移植性好、可多任务。 UC/OS-II 作为基于优先级的抢占式多任务的实时操作系统,包含了实时内核、任务管理、时间管理、任务间通信同步和内存管理的功能。它使得任务的独立性,不相互干涉,非常的准时和高效,且易于设计和扩展。 UO/OS-II 共有16个内核文件,11个与CPU 类型无关,就是说可以直接使用不需要修改。还有3个内核文件与CPU 有关系,要根据需要作出相应的改动。剩下的两个内核文件和具体的应用有关。如图所示UC/OS-II 的16个内核文件的层次。 μC/OS -II 内核文件 软件 硬件

多任务操作的核心是系统调度器,利用TCB来管理任务调度功能。它的主要功能是保存任务的当前态、优先级、等待事件、代码起始地址、初始堆栈指针等。程序的设计关键就是确定划分多任务的问题,以及任务优先级和任务通信。 优先级的意思是每个任务都是无限循环的,有运行态度、就绪态、休眠态、挂起态和中断五种状态。当有高一级优先级的任务就绪后,低优先级立即停止运行,转为挂起态或就绪态。这就是可剥夺型的内核。当中断一个高优先级任务,中断时 挂起,中断结束后任务继续运行,并立即剥夺低优先级的任务。 对于这种可剥夺型内核,CPU的使用时可以确定的,可优化任务级响应。在很多单片机或ARM板上很容易就可以移植UC/OS-II。当然本次设计使用的TQ2440,也可以完美的移植它。移植程序在网上都可以找得到,所以设计中就不做解释了。 本次设计实现的是串口协议和网口协议组合成的一个数据网关。其主要的流程图如下所示:

TCPIP协议规范及UIP处理流程

简要历史 1973年,ARPANET核心组成员Vint Cerf和Bob Kahn发表了一篇里程碑论文,阐述了实现分组的端到端交付的协议。这篇关于传输控制协议(TCP的论文包括:封装、数据报,以及网关的功能。 后来,TCP被划分为两个协议:传输控制协议(TCF)和网际互联协议(IP)。IP处理数据报的路由选 择,而TCP负责高层的一些功能,如分段、重装和差错检测。这个用来进行网际互联的协议后来就被称为TCP/IP。 TCP/IP协议族 简介 TCP/IP协议族由5层组成:物理层、数据链路层、网络层、运输层和应用层。前四层与OSI模型的前四层 相对应,提供物理标准、网络接口、网际互联、以及运输功能。而应用层与OSI模型中最高的三层相对应。 TCP/IP协议族中的各层包含了一些相对独立的协议。在物理层和数据链路层,TCP/IP并没有定义任何协议。 在网络层TCP/IP支持网际互联协议(IP),而IP又由四个支撑协议组成:ARP、RARP ICMP和IGMP。在传 统上,TCP/IP协议族在运输层有两个运输协议:TCP和UDP,然而现在已经设计出一个新的运输层协议SCTP 以满足新的应用的需要。IP是主机到主机的协议,即把分组从一个物理设备交付到另一个物理设备。UDP 和TCP是运输机协议,负责把报文从一个进程(运行着的程序)交付到另一个进程。 编址 使用TCP/IP协议的互联网使用3个等级的地址:物理(链路)地址、逻辑(IP)地址以及端口地址。 每一种地址属于TCP/IP体系结构中的特定层。 物理地址物理地址也叫链路地址,是结点的地址,由它所在的局域网或广域网定义。物理地址包含在数据链路层使用的帧中。 以太网的地址是6字节(48位)长,通常用十六进制记法,如:07:01:02:01:2C:4B。以太网的地址共 3 种:单播、多播和广播。在单播地址中的第一个字节的最低位0;在多播地址中的第一个字节的最低位 是1。广播地址是48 个1。 逻辑地址 因特网的逻辑地址是32位地址,可以用来标志连接在因特网上的每个主机。在因特网上没有两个主 机有相同的IP地址。同样,逻辑地址也可以是单播地址、多播地址和广播地址。 In ternet被各种路由器和网关设备分隔成很多网段,为了标识不同的网段,需要把32位的IP地址划分 成网络号和主机号两部分,网络号相同的各主机位于同一网段,相互间可以直接通信,网络号不同的主机之间通信则需要通过路由器转发。 把所有IP地址分为五类,如下图1所示: 图2-1 A 类到 B类到 C 类到 D 类到 E类到

嵌入式TCPIP协议栈

嵌入式TCPIP协议栈 嵌入式TCP/IP协议栈 目前,市场上几乎所有的嵌入式TCP/IP协议栈都是根据BSD版的TCP/IP协议栈改写的。在商业嵌入式TCP/IP协议栈大都相当昂贵的情况下,很多人转而使用一些源代码公开的免费协议栈,并加以改造应用。目前较为著名的免费协议栈有: lwIP(Light weight TCP/IP Stack)——支持的协议比较完整,一般需要多任务环境支持,代码占用ROM>40KB,不适合8位机系统,没有完整的应用文档; uC/IP(TCP/IP stack for uC/OS)—基于uC/OS的任务管理,接口较复杂,没有说明文档。 笔者采用的协议栈系瑞典计算机科学研究所Adam Dunkels开发的uIP0.9。其功能特性总结如下: *完整的说明文档和公开的源代码(全部用C语言编写,并附有详细注释); *极少的代码占用量和RAM资源要求,尤其适用于8/16位单片机(见表1); *高度可配置性,以适应不同资源条件和应用场合; *支持ARP、IP、ICMP、TCP、UDP(可选)等必要的功能特性; *支持多个主动连接和被动连接并发,支持连接的动态分配和释放; *简易的应用层接口和设备驱动层接口; *完善的示例程序和应用协议实现范例。 表1 uIP在ATMEL AVR上代码和RAM占用情况 协议模块代码大小/B 使用的RAM/B ARP 1324 118 IP/ICMP/TCP 3304 360 HTTP 994 110 校验和函数636 0 数据包缓存0 400 总和6258 988

注:配置为1个TCP听端口,10个连接,10个ARP表项,400字节数据包缓存。 正是由于uIP所具有的显著特点,自从0.6版本以来就被移植到多种处理器上,包括MSP430、AVR和Z80等。笔者使用的uIP0.9是2003年11月发布的版本。目前,笔者已将它成功移植到MCS-51上了。 2 uIP0.9的体系结构 uIP0.9是一个适用于8/16位机上的小型嵌入式TCP/IP协议栈,简单易用,资源占用少是它的设计特点。它去掉了许多全功能协议栈中不常用的功能,而保留网络通信所必要的协议机制。其设计重点放在IP、ICMP和TCP协议的实现上,将这三个模块合为一个有机的整体,而将UDP和ARP协议实现作为可选模块。UIP0.9的体系结构如图1所示。 UIP0.9处于网络通信的中间层,其上层协议在这里被称之为应用程序,而下层硬件或固件被称之为网络设备驱动。显然,uIP0.9并不是仅仅针对以太网设计的,以具有媒体无关性。 为了节省资源占用,简化应用接口,uIP0.9在内部实现上作了特殊的处理。 ①注意各模块的融合,减少处理函数的个数和调用次数,提高代码复用率,以减少ROM占用。 ②基于单一全局数组的收发数据缓冲区,不支持内存动态分配,由应用负责处理收发的数据。 ③基于事件驱动的应用程序接口,各并发连接采用轮循处理,仅当网络事件发生时 ,由uIP内核唤起应用程序处理。这样,uIP用户只须关注特定应用就可以了。传统的TCP/IP实现一般要基于多任务处理环境,而大多数8位机系统不具备这个条件。 ④应用程序主动参与部分协议栈功能的实现(如TCP的重发机制,数据包分段和流量控制),由uIP内核设置重发事件,应用程序重新生成数据提交发送,免去了大量内部缓存的占用。基于事件驱动的应用接口使得这些实现较为简单。 3 uIP的设备驱动程序接口 uIP内核中有两个函数直接需要底层设备驱动程序的支持。 一是uip_input()。当设置驱动程序从网络层收到的一个数据包时要调用这个函数,

uip学习笔记

uip_buf:定义如下u8_t uip_buf[UIP_BUFSIZE + 2];所有的数据处理都是通过处理它来完成的。比如接受的数据存储在这里,要发送的数据有会放在这里。 uip_len:uip_buf有用数据的字节 uip_appdata:uip_buf第一个可用字节的指针 uip_conn:总是指向当前连接的指针,定义:struct uip_conn *uip_conn; 下面是TCP连接的结构,用来区别不同的TCP连接,uip_tcp_appstate_t appstate是可以读写的且在实践应用中需要重定义,其他项read-only。 struct uip_conn { uip_ipaddr_t ripaddr; /**< The IP address of the remote host. 远程主机IP地址*/ u16_t lport; /**< The local TCP port, in network byte order. 本地TCP端口号,网络字节顺序*/ u16_t rport; /**< The local remote TCP port, in network byte order.本地远程连接主机TCP端口号*/ u8_t rcv_nxt[4]; /**< The sequence number that we expect to receive next. */ u8_t snd_nxt[4]; /**< The sequence number that was last sent by us. */ u16_t len; /**< Length of the data that was previously sent. */ u16_t mss; /**< Current maximum segment size for the connection. */ u16_t initialmss; /**< Initial maximum segment size for the connection. */ u8_t sa; /**< Retransmission time-out calculation state variable. */ u8_t sv; /**< Retransmission time-out calculation state variable. */ u8_t rto; /**< Retransmission time-out. */ u8_t tcpstateflags; /**< TCP state and flags. */ u8_t timer; /**< The retransmission timer. */ u8_t nrtx; /**< The number of retransmissions for the last segment sent. */ /** The application state. */ uip_tcp_appstate_t appstate; }; uip的应用事件: 1.接收数据:uip_newdata()为真,即远程连接的主机有发送新数据。uip_appdata指针指向实际数据。数据的大小通过uIP函数uip_datalen()获得。在数据不是被缓冲后,应用程序必须立刻启动。 2.发送数据:应用程序通过使用uIP函数uip_send()发送数据。uip_send()函数采用两个参数;一个指针指向发送数据和数据的长度。如果应用程序为了产生要发送的实际数据需要RAM 空间,包缓存(通过uip_appdata指针指向)可以用于这方面。在一个时间里应用程序只能在连接中发送一块数据。因此不可以在每个应用程序启用中调用uip_send()超过一次;只有上

无线物联网中CoAP协议的研究与实现

无线物联网中CoAP协议的研究与实现 作者:汤春明,张荧,吴宇平 引言 物联网是在互联网的基础上延伸和扩展的一种网络,其用户端延伸和扩展到了任何物品之间,彼此进行信息交换和通信,目的是实现所有物品与网络的连接,从而方便识别、管理和控制。 无线物联网的特点包括:全面感知、实时准确传递物品信息、利用智能计算技术对海量数据进行分析和处理,以实现智能化控制。 由于无线物联网中的设备很多都是资源受限型的,这些设备只有少量的内存空间和有限的计算能力。为此,IETF(Intemet Engineering Task Force)的CoRE(Constrained RESTful Environment)工作组为受限节点制定相关的REST(Representational State Transfer)形式的应用层协议。这就是CoRE工作组正在制订的CoAP(Constrained Application Protocol)协议。 1.6LoWPAN协议栈 由于TCP/IP协议栈不适用于资源受限的设备,因此提出了一种6LoWPAN(IPv6over Low power Wireless Personal Area Networks)协议栈。CoAP是6LoWPAN协议栈中的应用层协议。6LoWPAN使IPv6可用于低功耗的有损网络,它是基于IEEE802.15.4标准的。6LoWPAN协议栈如图1所示。 CoAP UDP IPv6层 IPv6—6LoWPAN适配层 802.15.4MAC 802.15.4PHY 图1 协议栈的下两层用802.15.4PHY/MAC,中间加一个IPv6-6LoWPAN适配层,传输层使用UDP协议,应用层使用CoAP协议。它包括REST的最小子集和到HTTP的无状态映射。通信主机使用CoAP协议,能够支持稳定的通信架构,以实现传感器节点与互联网的无线连接。 2.CoAP协议 在2010年3月,CoRE工作组开始制定CoAP协议,到目前为止,该协议还没有定稿。CoAP协议是为物联网中资源受限设备制定的应用层协议。它是一种面向网络的协

详解uIP TCPIP协议栈在51单片机上的设计实现

详解uIP TCPIP协议栈在51单片机上的设计实现 一引言 随着信息技术的不断发展,以及人们对日常生活舒适度、方便度要求的提高,信息家电、智能仪表等产品越来越频繁的出现在我们的生活当中;人们也越来越热衷于把家电、仪表等设备连接到Internet 中,从而可以方便、及时的对它们进行远程察看、远程控制。把这些设备接入Internet ,就需要考虑TCP/IP 网络协议的实现。 51单片机是对目前所有兼容Intel 8031指令系统的单片机的统称。该系列单片机的始祖是Intel的8031单片机,后来随着Flash rom技术的发展,8031单片机取得了长足的进展,成为目前应用最广泛的8位单片机之一,其代表型号是ATMEL公司的AT89系列,它广泛应用于工业测控系统之中。目前很多公司都有51系列的兼容机型推出,在目前乃至今后很长的一段时间内将占有大量市场。51单片机是基础入门的一个单片机,还是应用最广泛的一种。需要注意的是52系列的单片机一般不具备自编程能力。本文将简要描述uIP的实现方法,分析uIP协议栈的应用接口,并讨论如何将其应用到51系列单片机上。 二uIP协议栈的实现方法简述 uIP协议栈主要提供了三个函数供系统底层调用。即uip_init(),uip_input()和uip_periodic()。其与应用程序的主要接口是UIP_APPCALL()。ip_init()是系统初始化时调用的,主要初始化协议栈的侦听端口和默认所有连接是封闭的。当网卡驱动收到一个输进包时,将放进全局缓冲区uip_buf中,包的大小由全局变量uip_len约束。同时将调用uip_input ()函数,这个函数将会根据包首部的协议处理这个包和需要时调用应用程序。当uip_input ()返回时,一个输出包同样放在全局缓冲区uip_buf里,大小赋给uip_len.假如uip_len是0,则说明没有包要发送。否则调用底层系统的发包函数将包发送到网络上。uIP周期计时是用于驱动所有的uIP内部时钟事件。当周期计时激发,每一个TCP连接都会调用uIP函数uip_periodic()。类似于uip_input()函数。uip_periodic()函数返回时,输出的IP包要放到uip_buf中,供底层系统查询uip_len的大小发送。 uIP实现了TCP/IP协议集的四个基本协议:ARP地址解析协议,IP网际互联协议,ICMP 网络控制报文协议和TCP传输控制协议。为了在8位16位处理器上应用,uIP协议栈在各层协议实现时采用有针对性的方法,保持代码大小和存储器使用量最小。 1 实现ARP地址解析协议时为了节省存储器,ARP应答包直接覆盖ARP请求包。

如何学习TCPIP(基于51单片机)

如何学习TCPIP(基于51单片机) 总体说来,TCPIP并不是一件十分神秘的事情,尤其是基于MCU的应用,不要求进行特别复杂的处理,很多情况下只需要实现最最基本的功能就行了。在实现MCU的TCPIP移植之前,必须对TCPIP有一定程度的了解,可以找一本合适的书籍来翻阅一下,《TCP/IP详解,卷1:协议》https://www.360docs.net/doc/af11844320.html,/display.aspx?did=510是一本完整而详细的TCP/IP协议指南。描述了属于每一层的各个协议以及它们如何在不同操作系统中运行。 对于TCPIP在MCU上的应用并不要求对协议的所有部分都了解的那么清楚,重点需要了解TCPIP的各个层次的关系,链路层,有时也称作数据链路层或网络接口层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。它们一起处理与电缆(或其他任何传输媒介)的物理接口细节。网络层,有时也称作互联网层,处理分组在网络中的活动,例如分组的选路。在T C P / I P协议族中,网络层协议包括I P协议(网际协议),I C M P协议(I n t e r n e t互联网控制报文协议),以及I G M P协议(I n t e r n e t组管理协议)。运输层主要为两台主机上的应用程序提供端到端的通信。在T C P / I P协议族中,有两个互不相同的传输协议:T C P(传输控制协议)和U D P(用户数据报协议)。T C P为两台主机提供高可靠性的数据通信。它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。由于运输层提供了高可靠性的端到端的通信,因此应用层可以忽略所有这些细节。而另一方面,U D P则为应用层提供一种非常简单的服务。它只是把称作数据报的分组从一台主机发送到另一台主机,但并不保证该数据报能到达另一端。任何必需的可靠性必须由应用层来提供。这两种运输层协议分别在不同的应用程序中有不同的用途。应用层负责处理特定的应用程序细节。几乎各种不同的T C P / I P实现都会提供Telnet,FTP,SMTP 简单邮件传送协议,SNMP简单网络管理协议这些通用的应用程序。 各种类型的数据报格式也是需要了解的重点,使用Sniffer软件可以十分方便的在电脑上查看各种数据报的收发状态.同时Sniffer也是以后调试TCPIP协议寨的一个很有用的工具,Sniffer的使用方式可以在https://www.360docs.net/doc/af11844320.html,上很方便的搜索到. TCP/IP的分层,以太网封装,IP首部,子网寻址和子网掩码,ARP地址解析协议,ICMP控制报文协议中的ECHO(Ping程序),UDP用户数据报协议,TFTP简单文件传送协议,特别是TCP传输控制协议是TCPIP在MCU上应用所必需掌握的关键知识. 在对TCPIP有了一定程度的了解之后,如何具体的实现就成了问题的关键,我在学习TCPIP 的过程中前后一共使用或阅读了下面的3中TCPIP协议寨,这里有对3个协议寨的比较和下载地址. uIP,适合8bit单片机上使用,但是结构比较复杂,不适宜进行移植,也不是一份很适合阅读的代码.下载地址http://www.sics.se/~adam/uip/ Lwip,适合16/32bit单片机上使用,是嵌入式系统开发人员最好的学习TCPIP的代码,下载地址http://www.sics.se/~adam/lwip/ zLip,南开大学电子应用实验室编写的一个协议寨,有uip和lwip的优点,推荐初学者学习https://www.360docs.net/doc/af11844320.html,/display.aspx?did=859 在了解了具体实现之后,就有需要在MCU上具体的运行一下了,这里提供一个我做的硬件电路,但是其中我使用了GAL16V8芯片进行地址分配,所以需要有一个支持16V8的烧写器了,同时,如果将at89c55芯片换成sst89c58,并从https://www.360docs.net/doc/af11844320.html,公司网站上下载一个monitor 51的仿真监控程序,使用烧写器写入sst89c58中,就可以通过串口和Keil软件配合进行硬件仿真了.(市场上的那些100多元的51仿真器就是这个样子的). Gal的代码如下(abel hdl语言编写),使用猜测的方式都应该明白什么意思了把?!

uip协议栈下载

竭诚为您提供优质文档/双击可除 uip协议栈下载 篇一:uip之udp应用笔记 千兆网项目中,移植了uip到mcu中,采用udp通信方式,主要用来做一些控制协议的处理。刚开始接手的时候,并没有做过网络方面的应用,而且对tcp/ip及udp通信又不太熟悉。好在网上有一些文档,加上仔细阅读uip_process 代码,一边用抓包软件一边调试,总算把uip很好的应用了起来,而且还针对项目某些应用的特殊性,对uip源码进行了一些修改。本文前半部分对uip源码的一些重要函数进行介绍,后半部分将对修改的部分做个记录,以备往后查阅。 本次使用的是uip-1.0,抓包软件用的wireshark1.6.7,这个软件真的很不错,居然支持gigevision,这点真的很意外。 一、一个完整的udp数据报文格式 其实uip就是将你要发送到网络上的数据加上报头,好让它被成功发送到目的主机。所以我们要先搞清楚一个完整的数据报文,才能搞清楚uip到底在做些什么。 ethernetheader:由目标mac和本机mac及type组成,

共14byte,当目标mac全为ff时,表示是udp广播。 type=0x0800表示是ip。在uip中,ethernetheader结构体定义如下: ipheader:0x45表示version=4,headerlength=20byte;0028表示ipheader+udpheader+userdata长度为40byte; 6c14为包的id,每发一个包,这个id会自加1。80的意义是timetolive,表示这个包的存活时间,路由每转发一次,就会对它自减1。17表示通信协议类型为udp,4a0a为ipheader的校验码。再后面就是源ip和目的ip地址了。 udpheader:0aaa表示srcport为2730;0f74表示dstprot为3956;14表示udpheader+userdata长度为20byte,c477表示udpheader的校验码,在一般的情况下,这个可以为0。 在uip中,ipheader和udpheader结构体定义如下: userdata:再后面就是用户的数据了。 二、aRp数据报文格式 网络中是使用ip来标识主机的,而数据链路层的第一 道关卡是mac地址。因此ip和mac有一张动态映射表,而 这张表就是由aRp协议来建立并维护的。下面是一个aRp数据报文。 同样的,前面14byte是ethheader。hardwaretype对 于以太网来说为0001;0800表示是ipV4;06表示mac地址

基于FPGA的IP核8051上实现TCPIP的设计

基于FPGA的IP核8051上实现TCP/IP的设计引言 随着芯片规模的越来越大、资源的越来越丰富, 芯片的设计复杂度也大大增加。事实上, 在芯片设计完成后, 有时还需要根据情况改变一些控制, 这在使用过程中会经常遇到。这时候如果再对芯片设计进行改变将是很不可取的, 因为需要设计人员参与这种改变, 这无论是对设计者还是用户都是不能接受的。于是就有必要让这种可以改变的简单控制在芯片设计时就存在, 而且同时还应该使这种改变相对容易, 比较通用, 并且与芯片的其它设计部分尽量不相关。为了满足上述的要求, 在FPGA中嵌入一个比较理想的选择, 而这个即通用又控制简单的IP核最好选择8051微处理器。 在FPGA中植入8051后, 还可在上面实现简单的TCP/IP协议, 以支持远程访问或进行远程调试, 这只是在嵌入FPGA的8051上的一个应用。为了保证用户能够对8051实现不同的控制操作,设计时也可以采用一个外部flash对8051进行加载, 这样, 用户只需要将编译好的汇编语言代码加到flash就可以控制8051的工作, 而此时用户完全不需要对FPGA进行操作就能实现简单的控制,而这需要的仅仅只是keil的编译环境。 1 IP核8051的FPGA实现 现在有许多免费的8051核可以利用, 这些核都可通过硬件描述语言来实现, 并且基本上都可综合, 也就是直接拿来就能用, 需要的只是根据自身的具体需求做一些简单修改即可。总的说来, IP核8051的移植是比较简单的。 本系统的设计与实现可以采用oregano system的mc8051内核, 并且加入定时计数的和串口模块, 8051单片机的设计结构框图如图1所示。

OLC学习笔记及近期遇到OLC相关的故障和问题分析

OLC学习笔记及近期遇到OLC相关的故障和问题分析 1.OLC简介: OLC是OCS对外接机口,主要用作协议的转换和分发。消息的收发短信和语音协议的转换。--中转机器,进行协议解析、OCS处理分发 2.OLC配置简介: OLC包括的几个关键配置文件: 平台的配置文件imp.ini,配置OLC日志大小、最大个数,OLC接口参数等。 配置通讯节点的配置文件itcom.ini,包括本机OLC相关配置、OLC当客户端,连接OCS 的相关配置等。 具体业务进行配置的配置文件servicexxx.ini 下面是整理的配置过程中的一些注意事项: 3.OLC配置注意事项 itcom.ini配置注意事项: [general] module = 151 ; 节点号 postoffice = 176 ; 局号 areacode = 30 ; 区号 myipaddress = 10.40.51.27 ; 本机IP地址 alarmmodule = 133 ; 告警节点号 servercnt = 1 ; 服务器端配置数 clientcnt = 1 ; 客户端配置数 noLimitPort = 1 b、module和postoffice配置,此配置为其他主机连接的主要参数。提供给web\UIP及其其 他外部系统访问时用到的关键参数。 疑问: 320:58001|320:58009,58011,58023,58025,58027|220:65003,65005,65007,65009,65015,65017|3

20:58007|320:58019|320:58015|106:58003 前台配置的pno:220,从OLC上的配置怎么找,该Pno处理什么业务? c、noLimitPort配置由OCS主机/etc目录下的win_mgt.scr的[general]中的listenport值决定 的,如果为5000,需配置为0,其他配置为1。 如:OCS配置为listenport =5001,5010,OLC需要将noLimitPort = 1。 d、Module配置不可重复。如果部署多个OLC,每个OLC的Module不能重复。 如印尼项目生产环境: 雅加达配置: [general] module = 180 postoffice = 176 泗水配置: [general] module = 179 postoffice = 177 ----------------------------------------------------------------- [clientX]下的配置: [client1] mainpno = 380 myipaddress = 10.17.88.35 peeripaddress = 10.17.88.13 port = 5000 peermodule = 132 peerpost = 172 socketnum = 1 longconn = 1 commpno = 105 OLC为客户端、OCS或者其他为服务端。 关注peermodule,peerpost两个参数如何配置? Peermodule 表示对端模块号,常指OCS模块号 Peerpost 表示对端局号,常指OCS局号 可在OCS主机的/etc目录下,通过zxtool2 –v win_mgt.src的[general]查到对应的值。 如印尼项目现场: 雅加达OCS: [general] module=132 postoffice=172

相关文档
最新文档