之前发了一个帖子对于双网口的应用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()。。。。
例程在,最上面的连接中有 |