本帖最后由 a1153635534 于 2020-2-25 19:57 编辑
一种小型嵌入式TCP/ip协议的设计与实现
近年来小型设备连接到现存的 56 网诸如全球网的趋势愈演愈烈!而小型设备的接入技术一直是大家关注的焦点, 为了能使小型设备与通信, 实现一个短小精悍且占用资源比较少的 786956 协议栈则是其核心所在",因此!本文提出了一种小型的 786956 协议栈+,的完整的设计与实现" 这种协议栈的代码大小和所需; 远比现在其他通用的 786956 协议栈小! 并且实现了通用 786956 协议栈的大部分重要功能"完全符合的将代码体积和存储器使用压缩到最小的设计目的!从而能够适应单片机的有限资源 同时允许应用程序参与数据的重发!这样更能减少协议栈对资源的消耗.
可将smallIP视为一个为系统内核提供特定函数的代码库,图1表示出了smallIP与系统内核和应用程序之间的关系。small IP为系统内核主要提供了三个函数,分别为协议栈的初始化函数(ip__init(),接收网卡数据的函数(ip_input()),还有协议栈的定时触发函数(ip_periodic))。应用程序必须为smaallIP提供一-个callback函数,所谓callback函数就是由程序员自己编写而由系统调用的函数。当网卡驱动或时钟事件触发的时候,就调用callback函数small IP还为应用程序提供了大量的与协议栈进行交互的函数。考虑到速度、代码体积和协议栈的使用等问题,由small IP提供的大多数函数都是用C语言实现的.
在小型系统中运行一个多线程的环境实在是代价太大,不仅仅由于涉及线程管理的代码的复杂性增强,而且由于需要额外的存储器来管理每个线程的状态。这样也造成消耗在任务转换上的执行时间负荷增大。小型系统可能没有足够的资源来执行这样一个多线程环境,因此需要这种环境的应用程序接口并不适合smallIP。
相反,smallIP利用基于编程模型的事件机制,在这个编程模型里将应用程序作为一一个由small IP调用的响应某个事件的C函数。在发生以下情况的时候,small IP调用应用程序:当接收到数据的时候;当建立一个新的TCP连接的时候;当数据被成功传送到连接的另一端的时候;或者当重发数据的时候。应用程序也周期性的提交数据以维持“空闲连接”。应用程序仅仅提供一个callback函数,它负责将不同的网络服务映射到不同的端口和连接。
代码1
uip_ conn
结构体:
struct ip_ 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;
/*重传定时器*/
u8_ t
mss;
/*最大报文长度*/
u8_ _t appstate[IP_ _APPSTATE _SIZE];
如果smallIP的测试函数ip__newdata(的值为1,表示连接的远端主机已经发送了数据。指针ip_appdata指向当前数据。数据的大小通过smallIP的函数ip_ _datalen()得到。 因为数据不能被缓存,应用程序必须立即处理它。 应用程序利用协议栈函数ip_ send()发 送数据函数ip_ _send(包含两个参数:指向将要被发送的数据的指针和这个数据的长度。如果应用程序需要RAM产生将要被发送的数据,数据包缓存(被ip_ appdata 指针指向)可以用于这个目的。在一个连接上应用程序每次只能够发送唯-一一块数据,因此不可能不止一次地调用函数ip_send()。因为函数ip_ send0的调用将改变某个全局变量。在应用程序函数返回之前,它不应该被调用。 协议栈通过调用函数ip_ _stop0和函数ip_ _restart()控制TCP流量。考虑这样一个应用程序,它从一个服务器下载数据到一个慢速设备诸如磁盘驱动器。如果相对这个磁盘驱动器的工作队列很多,那么应用程序就不再从服务器接受任何数据直至工作队列被用完。用函数ip_ _stop()可让远 端主机停止发送数据。当应用程序准备更多数据的时候,用函数ip_ _restart()通 知远端主机重新开始发送数据。用函数ip_ stopped0检查当前的连接是否已经停止了。
|