硬汉嵌入式论坛

 找回密码
 立即注册
查看: 5223|回复: 1
收起左侧

[以太网] LWIP NETCONN 客户端问题经验分享

[复制链接]

32

主题

262

回帖

363

积分

高级会员

积分
363
发表于 2019-5-17 10:37:34 | 显示全部楼层 |阅读模式
本帖最后由 在水一方 于 2019-5-17 16:30 编辑

        之前发了一个帖子对于双网口的应用V7双网口同时使用LWIP,对源码进行了一些修改。已经重新上传。
        这里在做NETCONN客户端的时候硬汉大佬发现了个问题,给DM9162移植发送大数据的时候会卡死客户端连接,
昨天找了一天终于解决的。(DM9000的  是硬件驱动问题,这个目前还没打算调试)

1.对于ip4.c文件下的
struct netif *
my_ip4_route_src(const ip4_addr_t *src, const ip4_addr_t *dest)
{


}
函数修改,
修改前:
  /* iterate through netifs */
  NETIF_FOREACH(netif) {
    /* is the netif up, does it have a link and a valid address? */
    if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
      /* network mask matches? */
      if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) {
         /* return netif on which to forward IP packet */
         return netif;
      }
      /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */
      if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) {
        /* return netif on which to forward IP packet */
        return netif;
      }
    }
  }

      修改之前,LWIP的路由规则是基于目的地址和子网掩码进行netif选择的。这样会出现只会
选择同一个网段内的第一个netif。

修改后:
  /* iterate through netifs */
  NETIF_FOREACH(netif) {
    /* is the netif up, does it have a link and a valid address? */
    if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
      /* network mask matches? */
      if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) {
        if(ip_addr_cmp(src, netif_ip4_addr(netif))){
              /* return netif on which to forward IP packet */
          return netif;
        }
      }
      /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */
      if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) {
        /* return netif on which to forward IP packet */
        if(ip_addr_cmp(src, netif_ip4_addr(netif))){
              /* return netif on which to forward IP packet */
          return netif;
        }
      }
    }
  }

      加了一层源地址的判断 (  if(ip_addr_cmp(src, netif_ip4_addr(netif))) ),这样路由规则就知道,这个是
给谁的数据包了。

2.NETCONN客户端的测试
       排查了一下午发现NETCONN的 任务还在运行,但是无法接收数据,ping 还是能通,应该是协议栈或者
我创建的客户端有问题,我换成了ST提供的LWIP库,测试发现还是有问题。崩溃,无从下手。。。。
      开始仿真,发现任务还在运行指示 netconn_recv() 的返回值是超时,这下可能有点眉目了,因为我设置了
tcp_clientconn->recv_timeout = 10; 这里是这个客户端阻塞10ms,会不会数据大客户端阻塞时间不够,后来
把时间加大 tcp_clientconn->recv_timeout = 1000; 1秒的阻塞,发现完全没问题了,昨天晚上测试了近一个小时
再没出现卡死的现象,发送数据达到十几GB的数据流,没问题了。
     所以对于一些没没有接受时间要求的这个延时时间可以设大,或者设成0,FreeRTOS 设置0是永久等待的意思。


3.顺便说明下NETCONN的API加深记忆
3.1 netif_set_default(dm9162_netif);                         //设置netif为默认网口
        这里设置创建连接时,所需要的netif去设置默认值,因为创建连接时,是使用默认的netif创建的。


3.2 tcp_clientconn = netconn_new(NETCONN_TCP);          //创建一个TCP链接
        创建一个TCP连接控制块


3.3 err = netconn_connect(tcp_clientconn, &server_ipaddr, server_port); //连接服务器
        连接服务器


3.4 netconn_close(tcp_clientconn); //关闭 tcp_clientconn
关闭 连接 和 netconn_connect 一起使用的


3.5 netconn_delete(tcp_clientconn); //删除 tcp_clientconn
         和 netconn_new 一起使用的


3..6 netconn_recv()
        当使用 netconn_recv() 接收数据时,会调用 netconn_recv_data(),netconn_recv_data()又会调用
sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) 函数,这里是阻塞等待的。等待
内核任务发送数据包过来

3.7 netconn_write()
  真名 netconn_write_partly() ,这里面调用 netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
lwip_netconn_do_write()函数 ,调用 lwip_netconn_do_writemore(),在调用 tcp_write()。。。。
例程在,最上面的连接中有




回复

使用道具 举报

18

主题

321

回帖

375

积分

高级会员

积分
375
发表于 2019-5-17 10:42:24 | 显示全部楼层
老哥厉害了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-18 06:51 , Processed in 0.143717 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表