加载中…
个人资料
老衲五木
老衲五木
  • 博客等级:
  • 博客积分:0
  • 博客访问:353,222
  • 关注人气:330
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
博文
标签:

lwip

老衲五木

嵌入式网络那些事

视频教程

lwip常见问题

分类: LwIP常见问题

LwIP技术交流群(一群~八群)内每天很多新人加入,发现一个规律,很多问题都是新人必问的,所以在这里把这些问题做个汇总,方便大家实时查看,也避免了一次次重复回答同样问题的烦恼。这篇文章会实时更新,摘取我觉得大家问的最频繁,对大家理解LwIP以及TCP/IP协议最有用的话题。

1)LwIP到底稳定不稳定,能不能用在现实产品中。

首先要承认一点,世界上没有完美的软件,是软件就会有Bug,即便像Linux那样稳定和强大的系统,在极端和压力条件下,也会时不时爆出问题。LwIP源代码本生有Bug这个无可置疑(本人在其他几个文章中就罗列了好几个源代码上的问题),但我们要看到的是:LwIP版本在不断的迭代和更新,尤其是最近2.0版本出来后,就不断的更新,现在已经是最新的2.0.3了,作者们解决问题的态度和把LwIP做好的决心大家是有目共睹的。不像业界可能还存在的其他嵌入式网络协议栈,基本就处于无人维护,也无人使用的半死亡状态。

那么LwIP能不能用在现实产品中呢,我直接上一些干货,看看LwIP在哪些领域有应用,大家有兴趣的可以去详细了解。

a)基于LwIP的串口模块:有人物联串口模块,庆科串口WIFI模块,ES

标签:

lwip

老衲五木

嵌入式网络那些事

tcp连接异常

分类: LwIP常见问题
    LwIP所有版本包括最新的2.0版本具有以下缺陷,当用户使用raw编程并在err或poll回调函数中操作了内核全局tcp_active_pcbs链表(最典型的,比如进行了重连操作),将有可能导致链表异常,严重情况下,链表中的很多tcp_pcb会丢失,从而导致部分连接没有任何反应,出现假死的现象。
    具体信息为(以1.4.1为例),在tcp.c文件的tcp_slowtmr函数中,截取如下部分。
    请参考下面的蓝色步骤(1)->(2)->(3)->(4)->(5)->(6),该流程路径会引发问题。红色部分为需要添加的代码以修正这个BUG。
tcp_slowtmr_start:
  prev = NULL;
  pcb = tcp_active_pcbs;
  if (pcb == NULL) {
    LWIP_DEBUGF(TCP_DEBUG, ('tcp_slowtmr: no active pcbs\n'));
  }
  while (pcb != NULL) {
    if (pcb->last_timer == tcp_timer_ctr) {//(4)已经处理过的连接不再被处理
标签:

lwip

raw

tcp_tmr

sequentialapi

杂谈

分类: LwIP常见问题

网友来信:

五木您好! 
     感谢您在百忙之中抽空看我的邮件,抱歉今天又打扰您了,《嵌入式网络那些事:LwIP协议深度剖析与实战演练》已经买到了,在京东上买的,打8.5折,我也给我同事推荐了,大家最近被LwIP搞得有点晕,哈哈。
     我还有一些疑问想请教您一下:
    1、LwIP为我们提供了两种应用程序接口来实现TCP/IP协议栈,分别是RAW API和sequential API,我用的ARM芯片是STM32F103ZET6,ROM是512k,RAM是64K,跑的是uC/OS-II操作系统,您觉得用哪种应用程序接口好一点?
    2、我现在用的是RAW API应用程序接口实现TCP/IP协议栈,现在的情况是这样:我自己建了一个任务,这个任务用于与服务器建立通讯实现数据交换。我现在想在这个任务里建个应用程序框架,这个框架主要用于建立网络连接、接收服务器数据、发送数据给服务器,内核状态(pcb->state)查询、内核错误标志的处理和关闭网络连接等。我现在就是想:1、用个什么样的方法能够得到内核的工作状态,比如现在服务器发了关闭连接信号FIN,客户端此时会进入CLOSE_WAIT状态,那么在不改动内

标签:

lwip

tcp

接收窗口为0

raw

api

分类: LwIP常见问题

前两天网友来信,又是同样的一个问题,这也是好多基于raw api做开发的朋友最容易忽略的一个问题,来信原文摘录(陈兄,侵犯您版权啦。。。):

五木您好!
很荣幸在网上看到您发表的一些关于lwip的文章,写的非常好。
我现在有个小问题想请教您一下,就是服务器发命令给我,然后我回复服务器,在回复的TCP首部中,窗口一直在减少,最初是2920个字节,最后减成0了,然后服务器就不跟我通讯了。后来我把下面红色语句部分改成pcb->rcv_ann_wnd = pcb->rcv_wnd,使得rcv_ann_wnd是一个定值,但这样rcv_ann_right_edge 会在不停地变大,这样要不要紧呀,麻烦您指点我一下,非常感谢。
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)
{
u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd;
if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) {

pcb->rcv_ann_wnd = pcb->rcv_wnd;
return new_right_edge - pcb->rcv_ann_right_edge;
}
标签:

it

lwip

tcp

api

分类: 嵌入式网络那些事

    感谢广大机油吊丝们对《LwIP协议栈源码详解》的支持,经过一年半的完善与努力,该书的纸质版《嵌入式网络那些事:LwIP协议深度剖析与实战演练》已由中国水利水电出版社出版,图书基本信息及相关宣传见:

http://www.wsbookshow.com/plus/view.php?aid=11531,在当当、淘宝、京东等均可购买。

    新书电子版的写作风格类似,把原来电子版的10万字扩展到了35万字,同时增加了很多实用内容,包括LwIP原理与代码结构,详细移植过程,常用编程案例,常见的使用问题与解决方法等等~~~同时,结合LwIP代码,对TCP/IP的原理讲解也更生动丰富了一些~~

    不做王婆鸟。。有兴趣的童鞋看上面的传送。。

标签:

lwip

tcp

api

it

分类: 嵌入式网络那些事

函数netconn_new用来创建一个新的连接结构。连接结构的类型可以选择为TCP或UDP等。函数结构原型如下所示,参数type描述了连接的类型,可以为NETCONN_TCP或NETCONN_UDP等,这里都以TCP作为讨论的对象。

struct netconn* netconn_new(enum netconn_type type)

该函数首先调用netconn_alloc函数分配并初始化一个netconn结构。初始化的过程包括设置netconn结构类型字段,同时为该结构的op_completed创建一个信号量、recvmbox字段创建一个接收邮箱。奇怪的是netconn_alloc函数并不是在文件api_lib.c文件中,而是在api_msg.c中,凌乱!接下来函数netconn_new会构建一个api_msg消息,该消息要求内核执行函数do_newconn,最后函数tcpip_apimsg用来将消息包装成tcpip_msg结构并发送出去。tcpip_thread函数解析该消息并调用函数do_newconn,do_newconn根据参数的类型最终调用函数tcp_new创建一个TCP控制块。tcpip_apimsg会阻塞在一个信号量上,直至do_newconn释放该信号量。

函数netconn_delete用来删除一个连接结构netconn。与前面的流程相同,它通过

标签:

lwip

tcp

api

it

分类: 嵌入式网络那些事

现在有必要来看看前面一直提到的内核协议栈进程是什么样子的。这个函数叫tcpip_thread,其源码如下,其中去掉了不相关的编译选项和非重点讨论部分。

static void tcpip_thread(void *arg)

{

       struct tcpip_msg *msg;

       sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);//创建IP分片重装超时事件

       sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);// 创建ARP超时事件

       while (1) {                          // 进程循环

           sys_mbox_fetch(mbox, (void *)&msg);    // 阻塞在邮箱上接收要处理的消息

           switch (msg->type) {  // 判断消息类型

 &nb

标签:

lwip

tcp

it

分类: 嵌入式网络那些事

TCP还有最后一点东西需要扫尾。现在我们要跳出tcp_process函数,继续回到tcp_input中,前面说过,tcp_input接收IP

标签:

lwip

tcp

保活定时器

坚持定时器

it

分类: 嵌入式网络那些事

这节讲解TCP的坚持定时器和保活定时器,先看坚持定时器。

TCP的接收方通过通告窗口大小来告诉发送方自己可以接收的数据字节数,接收方采用这种方式来进行流量控制。假如接收方通告的窗口大小为 0会发生什么情况呢?这将有效地阻止发送方传送数据,直到通告窗口变为非0为止。

发送方接到0窗口通告时,则会停止数据段的发送,直到接收方通过非0的窗口。很重要的一点,TCP必须能够处理含新非0窗口通告的数据包丢失的情况,通常这个非0窗口通告是在一个不含任何数据的ACK包中发送的。ACK的传输并不可靠,也就是说, TCP不对ACK报文段进行确认(很明显,也就不会存在该ACK报文段的重发),TCP只确认那些包含有数据的ACK报文段。

如果一个确认丢失了,则双方就有可能因为等待对方而使连接终止:接收方等待接收数据(因为它已经向发送方通告了一个非 0的窗口),而发送方在等待允许它继续发送数据的非0窗口更新。为防止这种死锁情况的发生,发送方使用一个坚持定时器 (persist timer)来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送

标签:

lwip

tcp

重传

nagle

it

分类: 嵌入式网络那些事

前面介绍过,在收到一个失序的报文段时,该报文段会被挂接到ooseg队列上,同时向发送端返回一个ACK(期待的下一个字节),很明显,这个ACK一定是个重复的ACK,且这个重复的ACK被发送出去的时候不会有任何延迟。接收端利用该重复的ACK,目的在于让对方知道收到一个失序的报文段,并告诉对方自己希望收到的序号。

但是在发送方看来,它不可能知道一个重复的ACK是由一个丢失的报文段引起的,还是由于仅仅出现了几个报文段的重新排序引起。因此我们需要等待少量重复的ACK到来。假如这只是一些报文段的重新排序,则在重新排序的报文段被处理并产生一个新的ACK之前,只可能产生1 ~ 2个重复的ACK。如果一连串收到3个或3个以上的重复ACK,就非常可能是一个报文段丢失了。于是我们就重传丢失的数据报文段,而无需等待超时定时器溢出。这就是快速重传算法。在上节讲超时重传时说到,当超时发生后,ssthresh会被设置为有效发送窗口的一半,而cwnd被设置为一个报文段大小,即执行的是慢启动算法。而在这里,当执行完快速重传后,接下来执行的不是慢启动算法而是拥塞避免算法,这就是所谓的

  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有