当使用uIP 编写更大的应用程序时,以结构化的方式使用uIP API 是很有用的。下面的示例提供了一个结构化设计,表明它对于编写比前几节给出示例更复杂的协议实现非常有用。该程序分为一个uIP事件处理函数,它调用七个应用程序处理函数来处理新数据,作用于确认数据,发送新数据,处理连接建立或关闭事件以及处理错误,这些函数是newdata()、acked()、senddata()、connected()、closed()、aborted()和timedout(),需要专门为想要实现的协议编写这些函数。uIP事件处理函数如下所示:
该函数以首先处理通过检查uip_aborted()或uip_timedout()是否为真可能发生的任何错误开始,如果这两个函数值为真,则调用适当的错误处理函数,也就是如果连接已关闭,则会调用closed()函数来处理事件。
接下来,该函数通过检查函数uip_connected()是否为真来检查是否建立了连接,当连接建立时调用connected()函数并且假定完成了任何需要完成的操作,例如初始化该连接的应用程序状态,因为可能发送了数据,因此调用senddata()函数来处理输出数据。
下面应用程序作为应用程序处理函数的结构,该应用程序仅仅等待连接上到达的任何数据,并通过发送消息“Hello world!”来响应数据,为了说明如何设计应用程序状态机,该消息分为两部分发送,首先是“Hello”部分,然后是“world!”部分。
应用程序状态包括“状态”变量,指向文本消息的“textptr”指针和文本消息的长度“textlen”。“state” 变量可以是“STATE_WAITING”“STATE_HELLO”或“STATE_WORLD”。“STATE_WAITING”意味着应用程序正在等待来自网络的数据,“STATE_HELLO”表示应用程序正在发送消息的“Hello”部分,“STATE_WORLD”表示应用程序正在发送“world!”信息。(www.xing528.com)
应用程序不处理错误或连接关闭事件,因此aborted()、timedout()和closed()函数实现为空函数。建立连接时将调用connected()函数,在这种情况下,将“state”变量设置为“STATE_WAITING”,将“textlen”变量设置为零,表示没有要发送的消息。当新数据从网络到达时,newdata()函数将由事件处理函数调用。newdata()函数将检查连接是否处于“STATE_WAITING”状态,如果是,则切换到“STATE_HELLO”状态,并在连接中注册一个6 字节长的“Hello”消息。稍后将通过senddata()函数发送此消息。
只要接收主机已确认先前发送的数据,就会调用acked()函数,acked()函数首先通过从“textlen”变量中减去从“uip_conn-> len”获得的先前发送数据的长度来减少要发送的数据量,并调整“textptr”指针;然后检查“textlen”变量现在是否为零,这表示现在所有数据都已成功接收,如果为零,则更改应用程序状态。如果应用程序处于“STATE_HELLO”状态,则将状态切换为“STATE_WORLD”并设置要发送的7 个字节“world!\n”消息。如果应用程序处于“STATE_WORLD”状态,则会关闭连接。
最后,senddata()函数负责实际正在发送的数据,当接收到新数据、确认数据、建立新连接、因不活动而轮询连接或进行重传时,事件处理函数调用senddata()函数。 senddata()函数的目的是选择格式化要发送的数据,并调用uip_send()函数来实际发送数据。在这个特定的例子中,如果要发送数据,函数只是调用带有适当参数的uip_send()函数,检查是否应该发送数据。重要的是,要注意senddata()函数永远不应该影响应用程序状态,这应该只在acked()和newdata()函数中完成。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。