guxingganyue 发表于 2019-1-17 15:01:27

Lwip 2.1.2用netconn_accept建立的server被close,重建后client重连失败

用Lwip 2.1.2的netconn_accept建立的server,client(电脑模拟)第一次可以连接成功,收发数据正常。关闭client(和server的连接也就断开了),当第二次再连接server就无法连接成功了,这是为什么呢?理论上第一次可以成功,后面都可以成功的呢

说明:程序中有下面的2句话,非常的重要,加上后当有一个client和server连接时其他client就无法连接server了,不加的话,其他client还是可以连接成功server,但是无法通信
netconn_close(tcp_serverconn);//关闭tcp_serverconn连接
netconn_delete(tcp_serverconn); //删除tcp_serverconn连接


主要代码如下,欢迎大家讨论
void TCP_Server(void *pdata)
{
err_t err;
struct pbuf *q;
struct netconn *tcp_serverconn, *newconn;
struct netbuf *recvbuf;

while (1)
{
    tcp_serverconn = netconn_new(NETCONN_TCP);      //新建一个netconn连接
    netconn_bind(tcp_serverconn, IP_ADDR_ANY, 12345); //绑定ip和端口号
    netconn_listen(tcp_serverconn);                   //开始监听

    //阻塞等待client连接,连接成功的话会建立了一个新的netconn连接: newconn
    netconn_accept(tcp_serverconn, &newconn);         

    //程序到这里说明已经有一个client连接成功
    //加入下面这2句话的原因:已经有一个client连接到server后防止其他client再连接到server上。
    //不关闭这个连接的话,其他client可以成功连接到tcp_serverconn上,但是无法收发数据
    netconn_close(tcp_serverconn);//关闭tcp_serverconn连接
    netconn_delete(tcp_serverconn); //删除tcp_serverconn连接
    while (1)
    {
      if ((err = netconn_recv(newconn, &recvbuf)) == ERR_OK)
      {
      //·······
      netbuf_delete(recvbuf);
      
      if(收到退出命令)
      {
          netconn_close(newconn); //关闭 newconn 连接
          netconn_delete(newconn);//释放 newconn 资源
          break;                  //退出内while1,去外层while1,
      }
      }
    }
}
}

guxingganyue 发表于 2019-1-17 17:48:31

自己顶一顶,,,,刚才调试了无任何进展。
抓包分析是client请求连接后,server会了,直接把连接给断了,这是闹哪样

onepower 发表于 2019-1-17 17:51:17

唉~~~~ lwip都出来这么久了, 用起来 lwip的bug, 还是好多~~~~

guxingganyue 发表于 2019-1-18 09:01:38

onepower 发表于 2019-1-17 17:51
唉~~~~ lwip都出来这么久了, 用起来 lwip的bug, 还是好多~~~~

嗯,本来这个协议栈就比较复杂,一直在修修补补,如有大的调整,bug就又有了

guxingganyue 发表于 2019-1-18 09:58:46

打开了debug后输出的信息如下:提示我的pcb被用完了?第一次用的时候都好好的,删除后把tcp也给删了?
即使把opt文件中tcp的数量增大,提示也是一样的
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
//------第一次连接成功
TCP connection request 14377 -> 12345.
TCP connection established 14377 -> 12345.
tcp_close: closing in State: LISTEN
//----------------------------------------
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
//------第一次断开,断开正常
tcp_recved: window got too big or tcpwnd_size_t overflow
tcp_recved: received 1 bytes, wnd 11680 (0).
tcp_close: closing in State: CLOSE_WAIT
TCP connection closed: LAST_ACK 14377 -> 12345.
tcp_pcb_purge
//-----------------------------
tcp_slowtmr: polling application
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_slowtmr: processing active pcb

//---------第二次连接,提示没有pcb了,这是怎么回事,pcb被谁用了?
tcp_input: no PCB match found, resetting.
tcp_rst: seqno 0 ackno 3635802904.
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_input: no PCB match found, resetting.
tcp_rst: seqno 0 ackno 3635802904.
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_slowtmr: processing active pcb
tcp_input: no PCB match found, resetting.
tcp_rst: seqno 0 ackno 3635802904.
//---------重连结束,client不再连接
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcp_slowtmr: processing active pcb
tcp_slowtmr: processing active pcb

guxingganyue 发表于 2019-1-18 10:09:54

这篇文章中支出了lwip会丢失pcb的问题,但是我用的2.1.2中已经把这句话加入了,不应该再丢失pcb了啊


guxingganyue 发表于 2019-1-18 12:44:07

问题已经解决,主要是加入了超时控制语句:tcp_serverconn->recv_timeout=200;
具体程序如下:
void TCP_Server(void *pdata)
{
err_t err;
struct pbuf *q;
struct netconn *tcp_serverconn, *newconn;
struct netbuf *recvbuf;

while (1)
{
    tcp_serverconn = netconn_new(NETCONN_TCP);      //新建一个netconn连接
    netconn_bind(tcp_serverconn, IP_ADDR_ANY, 12345); //绑定ip和端口号
    netconn_listen(tcp_serverconn);                   //开始监听
   
    tcp_serverconn->recv_timeout=200;               //---------这个非常重要哦

    err=netconn_accept(tcp_serverconn, &newconn);         
    if(err==ERR_OK)
    {
      netconn_close(tcp_serverconn);//关闭tcp_serverconn连接
      netconn_delete(tcp_serverconn); //删除tcp_serverconn连接
      while (1)
      {
      if ((err = netconn_recv(newconn, &recvbuf)) == ERR_OK)
      {
          //·······
          netbuf_delete(recvbuf);
         
          if(收到退出命令)
          {
            netconn_close(newconn); //关闭 newconn 连接
            netconn_delete(newconn);//释放 newconn 资源
            break;                  //退出内while1,去外层while1,
          }
      }
      }
    }
    else
    {
      netconn_delete(tcp_serverconn);
    }
}
}

hpdell 发表于 2019-1-23 16:10:56

guxingganyue 发表于 2019-1-18 12:44
问题已经解决,主要是加入了超时控制语句:tcp_serverconn->recv_timeout=200;
具体程序如下:
...

牛逼呀,厉害呀,学习学习了

saccapanna 发表于 2019-1-23 16:44:48

2.0.3 版本连续运行了十多天做压力测试,没测出这个问题,2.0.3有丢失PCB的问题吗?

kinsno 发表于 2019-1-23 18:22:41

saccapanna 发表于 2019-1-23 16:44
2.0.3 版本连续运行了十多天做压力测试,没测出这个问题,2.0.3有丢失PCB的问题吗? ...

这点时间算什么,以年的时间来看看,你就知道了,我已经打算放弃这个东西了。

guxingganyue 发表于 2019-1-23 18:34:25

saccapanna 发表于 2019-1-23 16:44
2.0.3 版本连续运行了十多天做压力测试,没测出这个问题,2.0.3有丢失PCB的问题吗? ...

2.0.3好像比2.1.2在client上要稳定些。。下次不得已的话不用lwip了,出问题解决太花时间了。。。

guxingganyue 发表于 2019-1-23 18:35:14

kinsno 发表于 2019-1-23 18:22
这点时间算什么,以年的时间来看看,你就知道了,我已经打算放弃这个东西了。 ...

是的,下次我也不优先考虑这个东西了。。。。

guxingganyue 发表于 2019-1-23 18:39:42

kinsno 发表于 2019-1-23 18:22
这点时间算什么,以年的时间来看看,你就知道了,我已经打算放弃这个东西了。 ...

有稳定的推荐吗

saccapanna 发表于 2019-1-23 20:06:58

kinsno 发表于 2019-1-23 18:22
这点时间算什么,以年的时间来看看,你就知道了,我已经打算放弃这个东西了。 ...

做连接异常监测啊,如果不能恢复连接就复位,目前来看LWIP还是挺稳定的,但的确也有bug。比如发送阻塞死任务,比如再IAR下只能低优化等级,中高级优化都会存在问题(阻塞死,概率很高)。V2.0.3做TCP客户端,目前修改配置,调整内存,使用低优化等级,没出现过问题了。另外修改了一下协议栈代码,发送加了超时处理,异常情况都能恢复。

saccapanna 发表于 2019-1-23 20:10:30

guxingganyue 发表于 2019-1-23 18:34
2.0.3好像比2.1.2在client上要稳定些。。下次不得已的话不用lwip了,出问题解决太花时间了。。。 ...

W5500自带协议栈,也还是挺稳定的,我用STM32的DMA模式,不跑其他任务,也能做到40Mbps,正常使用16Mbps可以很稳定。速度要求不高可以考虑。

guxingganyue 发表于 2019-1-23 21:23:29

saccapanna 发表于 2019-1-23 20:10
W5500自带协议栈,也还是挺稳定的,我用STM32的DMA模式,不跑其他任务,也能做到40Mbps,正常使用16Mbp ...

嗯,下次可以试试这个硬件的协议栈。。。

guxingganyue 发表于 2019-1-24 11:41:37

kinsno 发表于 2019-1-23 18:22
这点时间算什么,以年的时间来看看,你就知道了,我已经打算放弃这个东西了。 ...

昨天2.1.2过夜测试,pcb又丢了【mcu的client不连接服务器了,mcu server还工作正常】。。监听发现连mcu的client发给服务器的端口号都变了,本来要发60123的,pcb丢失后就变成9000多了

注:我的lwip跑,tcp client,向服务器300ms发送一次数据,服务器每隔100ms发给client 16字节数据;tcp server监听电脑上的client的连接,并回复相关的指令。

pcb被用光了

端口号被改变了

kinsno 发表于 2019-1-25 13:06:43

guxingganyue 发表于 2019-1-24 11:41
昨天2.1.2过夜测试,pcb又丢了【mcu的client不连接服务器了,mcu server还工作正常】。。监听发现连mcu的 ...

这个家伙有的折腾,我打算改版了,换rl-net协议栈了。

kinsno 发表于 2019-1-25 13:08:09

saccapanna 发表于 2019-1-23 20:06
做连接异常监测啊,如果不能恢复连接就复位,目前来看LWIP还是挺稳定的,但的确也有bug。比如发送阻塞死 ...

你是修改了源码,你是用底 层netconn ? 还是用的socket,我直接用的socket。。如果你修改过,修改后的源码方便分亨一下不?

saccapanna 发表于 2019-1-25 18:23:23

kinsno 发表于 2019-1-25 13:08
你是修改了源码,你是用底 层netconn ? 还是用的socket,我直接用的socket。。如果你修改过,修改后的源 ...

就是发送信号量加了一个超时,这是治标的办法,如果发送阻塞了,基本就挂壁了。这种情况下可以做复位处理,不过修改配置后,已经没出现过了。不开优化,调整配置试试,不行用V2.0.3吧,做客户端,我觉得这个版本还是挺稳定的。

guxingganyue 发表于 2019-1-25 21:40:15

kinsno 发表于 2019-1-25 13:06
这个家伙有的折腾,我打算改版了,换rl-net协议栈了。

嗯,这个得用MDK,软件不敢联网,且现在应用层做的差不多了,换这个动作有点大。。

我后来换2.0.3,到今天为止没出现啥问题,下周一再看看

guxingganyue 发表于 2019-1-25 21:45:49

saccapanna 发表于 2019-1-25 18:23
就是发送信号量加了一个超时,这是治标的办法,如果发送阻塞了,基本就挂壁了。这种情况下可以做复位处理 ...

1、修改配置是修改lwipopts文件吗?主要改了哪个参数呢?
2、有没有兴趣把你的lwip换成2.1.2试试client呢?

目前看tcp client 2.0.3确实比2.1.2要稳定,带os情况下。。其他应用没有用。client用netconn方式

kinsno 发表于 2019-1-26 13:14:53

guxingganyue 发表于 2019-1-25 21:40
嗯,这个得用MDK,软件不敢联网,且现在应用层做的差不多了,换这个动作有点大。。

我后来换2.0.3,到今 ...

你是说2.0.3版本比2.1.2更稳定吗,我使用的是SOCKET,虽然效率挫点,但应用层更兼容啊。

kinsno 发表于 2019-1-26 13:15:48

saccapanna 发表于 2019-1-25 18:23
就是发送信号量加了一个超时,这是治标的办法,如果发送阻塞了,基本就挂壁了。这种情况下可以做复位处理 ...

好象楼主在上面某楼也说了,用2.0.3版稳定,你也觉得这个版本稳定,对吗?那我下次可以试着用这个版本。

guxingganyue 发表于 2019-1-26 15:12:02

kinsno 发表于 2019-1-26 13:14
你是说2.0.3版本比2.1.2更稳定吗,我使用的是SOCKET,虽然效率挫点,但应用层更兼容啊。

...

是的,2.0.3我从差不多用了一年了,去年12月蛋疼就升到了2.1.2,最近被它折腾的好惨。。还是继续用2.0.3吧

socket我没用,一直用netconn方式。

kinsno 发表于 2019-1-26 18:10:19

guxingganyue 发表于 2019-1-26 15:12
是的,2.0.3我从差不多用了一年了,去年12月蛋疼就升到了2.1.2,最近被它折腾的好惨。。还是继续用2.0.3 ...

如果是service和client同时并存的话,能用netconn吗? 因为我的需求是 这2种模式并存,既要作为服务器接受客户的数据,又要向上级服务器汇报数据,要承上启下的工作。。

guxingganyue 发表于 2019-1-26 22:39:22

kinsno 发表于 2019-1-26 18:10
如果是service和client同时并存的话,能用netconn吗? 因为我的需求是 这2种模式并存,既要作为服务器接 ...

可以的,一个线程做client把数据传给服务器,另一个线程做server,等待client的连接。这2个线程设置不同的端口号即可。。。

kinsno 发表于 2019-1-26 22:41:56

guxingganyue 发表于 2019-1-26 22:39
可以的,一个线程做client把数据传给服务器,另一个线程做server,等待client的连接。这2个线程设置不同 ...

妥了,下次可以尝试用这个了,哈哈。。现在还没有太大兴趣折腾它。。

guxingganyue 发表于 2019-1-27 17:45:52

kinsno 发表于 2019-1-26 22:41
妥了,下次可以尝试用这个了,哈哈。。现在还没有太大兴趣折腾它。。

...

恩,现在你已经切到rl-tcpnet了?

saccapanna 发表于 2019-1-27 19:23:58

kinsno 发表于 2019-1-26 18:10
如果是service和client同时并存的话,能用netconn吗? 因为我的需求是 这2种模式并存,既要作为服务器接 ...

非常肯定告诉你,可以!我做测试时,跑了一个server,三个client,共四个连接,很稳定。

kinsno 发表于 2019-1-27 19:52:21

saccapanna 发表于 2019-1-27 19:23
非常肯定告诉你,可以!我做测试时,跑了一个server,三个client,共四个连接,很稳定。 ...

你是用2.03版本,对吗?使用的也是和楼主一个的netcon模式吗吗,还是采用通用的SOCKET啊。

kinsno 发表于 2019-1-27 19:52:51

guxingganyue 发表于 2019-1-27 17:45
恩,现在你已经切到rl-tcpnet了?

有计划,但还没有实施,{:sweat:},节后3月份就要启动了。。


saccapanna 发表于 2019-1-27 20:38:00

kinsno 发表于 2019-1-27 19:52
你是用2.03版本,对吗?使用的也是和楼主一个的netcon模式吗吗,还是采用通用的SOCKET啊。

...

v2.0.3netcon

guxingganyue 发表于 2019-1-27 21:11:54

saccapanna 发表于 2019-1-27 20:38
v2.0.3netcon

兄弟,22楼的问题能给回复下不?

saccapanna 发表于 2019-1-27 23:01:51

guxingganyue 发表于 2019-1-25 21:45
1、修改配置是修改lwipopts文件吗?主要改了哪个参数呢?
2、有没有兴趣把你的lwip换成2.1.2试试client呢 ...

配置问题,就是修改lwip的配置文件,几句话讲不清楚,建议仔细阅读一下资料,把每个配置的意义搞懂,总之buff要大一些。目前暂时没时间测试2.1.2,有空了可以试试。

guxingganyue 发表于 2019-1-28 08:56:14

saccapanna 发表于 2019-1-27 23:01
配置问题,就是修改lwip的配置文件,几句话讲不清楚,建议仔细阅读一下资料,把每个配置的意义搞懂,总之 ...

好的,谢谢啦。

saccapanna 发表于 2019-1-28 09:00:06

guxingganyue 发表于 2019-1-25 21:45
1、修改配置是修改lwipopts文件吗?主要改了哪个参数呢?
2、有没有兴趣把你的lwip换成2.1.2试试client呢 ...


/**
******************************************************************************
* File Name          : lwipopts.h
* Description      : This file overrides LwIP stack default configuration
*                      done in opt.h file.
******************************************************************************
* This notice applies to any and all portions of this file
* that are not between comment pairs USER CODE BEGIN and
* USER CODE END. Other portions of this file, whether
* inserted by the user or by software development tools
* are owned by their respective copyright owners.
*
* Copyright (c) 2018 STMicroelectronics International N.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
*    contributors to this software may be used to endorse or promote products
*    derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
*    software, must execute solely and exclusively on microcontroller or
*    microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
*    this license is void and will automatically terminate your rights under
*    this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/

/* Define to prevent recursive inclusion --------------------------------------*/
#ifndef __LWIPOPTS__H__
#define __LWIPOPTS__H__

#include "stm32f4xx_hal.h"
#include <common.h>



/*-----------------------------------------------------------------------------*/
/* Current version of LwIP supported by CubeMx: 2.0.3 -*/
/*-----------------------------------------------------------------------------*/

/* Within 'USER CODE' section, code will be kept by default at each generation */
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

#ifdef __cplusplus
extern "C" {
#endif

/* STM32CubeMX Specific Parameters (not defined in opt.h) ---------------------*/
/* Parameters set in STM32CubeMX LwIP Configuration GUI -*/



//==============================================================================================================
// WITH_RTOS = 1: 使用操作系统
// WITH_RTOS = 0: 不使用操作系统
//==============================================================================================================
#define WITH_RTOS                     (1u)

//==============================================================================================================
// CHECKSUM_BY_HARDWARE disabled
//==============================================================================================================
#define CHECKSUM_BY_HARDWARE            (0u)

//==============================================================================================================
// Value in opt.h for LWIP_DHCP: 0
// LWIP_DHCP = 0:关闭 DHCP 功能
// LWIP_DHCP = 1:开启 DHCP 功能,可以自动分配IP地址。
//==============================================================================================================
#define LWIP_DHCP                     (1u)

//==============================================================================================================
// Default Value for LWIP_DNS: 0
// LWIP_DNS = 0:关闭 DNS 功能
// LWIP_DNS = 1:开启 DNS 功能,可以支持域名解析功能。
//==============================================================================================================
#define LWIP_DNS                        (1u)

//==============================================================================================================
// Default Value for MEMP_NUM_NETCONN: 4
// MEMP_NUM_NETCONN: the number of struct netconns.
// (only needed if you use the sequential API, like api_lib.c)
//==============================================================================================================
#define MEMP_NUM_NETCONN                (8u)

//==============================================================================================================
// Default Value for MEMP_NUM_UDP_PCB: 4
// MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
// per active UDP "connection".
// (requires the LWIP_UDP option)
//==============================================================================================================
#define MEMP_NUM_UDP_PCB                (4u)

//==============================================================================================================
// Default Value for MEMP_NUM_TCP_PCB: 5
// MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections.
// (requires the LWIP_TCP option)
//==============================================================================================================
#define MEMP_NUM_TCP_PCB                (8u)

//==============================================================================================================
// Default Value for MEMP_NUM_TCP_PCB_LISTEN: 8
// MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections.
// (requires the LWIP_TCP option)
//==============================================================================================================
#define MEMP_NUM_TCP_PCB_LISTEN         (8u)

//==============================================================================================================
// Value in opt.h for MEM_ALIGNMENT: 1
// 内存对齐方式,STM32 是32位机,使用 4 字节对齐。
//==============================================================================================================
#define MEM_ALIGNMENT                   (4u)

//==============================================================================================================
// Value in opt.h for MEM_SIZE: 1600
// MEM_SIZE: the size of the heap memory. If the application will send
// a lot of data that needs to be copied, this should be set high.
// 内存堆大小定义,如果要发送大量的需要复制的数据,这个需要设置大一点。默认值是 1600
// 单位:字节
// Heap 设置多大,基本就需要多大的内存。
//==============================================================================================================
#define MEM_SIZE                        (32*1024u)

//==============================================================================================================
// Value in opt.h for MEMP_NUM_PBUF: 16
// MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF).
// If the application sends a lot of data out of ROM (or other static memory),
// this should be set high.
// MEMP_NUM_PBUF: memp结构的pbuf数量,如果应用从ROM或者静态存储区发送大量数据时,设置大一些。
// 修改这个值,编译后对内存的影响不大,16Byte * N。
//==============================================================================================================
#define MEMP_NUM_PBUF                   (192u)

//==============================================================================================================
// Value in opt.h for MEMP_NUM_TCPIP_MSG_API: 8
// MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
// for callback/timeout API communication.
// (only needed if you use tcpip.c)
// tcpip_msg 数量,用于回调、超时等API应用。
// 修改这个值,编译后对内存的影响不大,16Byte * N
//==============================================================================================================
#define MEMP_NUM_TCPIP_MSG_API          (192u)

//==============================================================================================================
// Value in opt.h for MEMP_NUM_TCPIP_MSG_INPKT: 8
// MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
// for incoming packets.
// (only needed if you use tcpip.c)
// tcpip_msg 数量,用于输入数据接收。
// 修改这个值,编译后对内存的影响不大,16Byte * N
//==============================================================================================================
#define MEMP_NUM_TCPIP_MSG_INPKT      (192u)

//==============================================================================================================
// Value in opt.h for PBUF_POOL_SIZE: 16
// PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
//
// pbuf 内存池个数
// PBUF_POOL_SIZE *( PBUF_POOL_BUFSIZE + header ) = 内存池需要的大小。
// 修改这两个值,对内存的占用影响很大。
//
// PBUF_POOL_SIZE * PBUF_POOL_BUFSIZE 必须要比 TCP_WND 和 TCP_SND_BUF 大。
// 修改参数时,注意检测这几个宏之间的关系。
//==============================================================================================================
#define PBUF_POOL_SIZE                  (32u)

//==============================================================================================================
// PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is
// designed to accommodate single full size TCP frame in one pbuf, including
// TCP_MSS, IP header, and link header.
// PBUF_POOL_BUFSIZE = LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)
//
// pbuf 内存池大小,单个 pbuf 能存下一个完整的 TCP 帧,完整的 TCP 帧大小:
// TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN = 1460 + 40 + 0 + 18 = 1518
//==============================================================================================================
#define PBUF_POOL_BUFSIZE               (1520u)

//==============================================================================================================
// TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default,
// you might want to increase this.)
// For the receive side, this MSS is advertised to the remote side
// when opening a connection. For the transmit size, this MSS sets
// an upper limit on the MSS advertised by the remote host.
// 最大TCP数据分段,加大这个值可以提高通信速率,但是会占用更多的内存。默认值 536.
// TCP 协议在建立连接时,会协商 MSS 值
//==============================================================================================================
#define TCP_MSS                         (1460u)

//==============================================================================================================
// TCP_WND: The size of a TCP window.This must be at least
// (2 * TCP_MSS) for things to work well.
// ATTENTION: when using TCP_RCV_SCALE, TCP_WND is the total size
// with scaling applied. Maximum window value in the TCP header
// will be TCP_WND >> TCP_RCV_SCALE
// 注意:TCP_WND是发送窗口,这个值对于LWIP的速度影响非常大。
//       TCP_WND 不能大于 PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers).
//==============================================================================================================
#define TCP_WND                         (24 * TCP_MSS)

//==============================================================================================================
// TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an
// explicit window update
// Value in opt.h for TCP_WND_UPDATE_THRESHOLD: LWIP_MIN(TCP_WND/4, TCP_MSS*4)
//==============================================================================================================
#define TCP_WND_UPDATE_THRESHOLD      (4 * TCP_MSS)

//==============================================================================================================
// TCP_SND_BUF: TCP sender buffer space (bytes).
// To achieve good performance, this should be at least 2 * TCP_MSS.
//==============================================================================================================
#define TCP_SND_BUF                     (24 * TCP_MSS)

//==============================================================================================================
// TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
// as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
//==============================================================================================================
#define TCP_SND_QUEUELEN                ((8 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS))

//==============================================================================================================
// MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments.
// (requires the LWIP_TCP option)
// MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN.
// MEMP_NUM_TCP_SEG: 最多同时在队列中的TCP段数量,至少要和 TCP_SND_QUEUELEN 一样大。
//==============================================================================================================
#define MEMP_NUM_TCP_SEG                (256u)

//==============================================================================================================
// LWIP_ETHERNET==1: enable ethernet support even though ARP might be disabled
// Value in opt.h for LWIP_ETHERNET: LWIP_ARP || PPPOE_SUPPORT -
//==============================================================================================================
#define LWIP_ETHERNET                   (1u)

//==============================================================================================================
// TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread.
// The stack size value itself is platform-dependent, but is passed to
// sys_thread_new() when the thread is created.
// TCPIP_THREAD 任务栈大小,平台相关配置,注意:单位是4字节
//
// TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread.
// The priority value itself is platform-dependent, but is passed to
// sys_thread_new() when the thread is created.
//      osPriorityIdle          = -3,          ///< priority: idle (lowest)
//      osPriorityLow         = -2,          ///< priority: low
//      osPriorityBelowNormal   = -1,          ///< priority: below normal
//      osPriorityNormal      =0,          ///< priority: normal (default)
//      osPriorityAboveNormal   = +1,          ///< priority: above normal
//      osPriorityHigh          = +2,          ///< priority: high
//      osPriorityRealtime      = +3,          ///< priority: realtime (highest)
// 优先级说明:这个是 CubeMX 为了兼容性而修改的枚举类型,对于FreeRTOS,实际优先级等级要加3.
//==============================================================================================================
#define TCPIP_THREAD_STACKSIZE          (512u)
#define TCPIP_THREAD_PRIO               osPriorityHigh
#define SLIPIF_THREAD_STACKSIZE         (512u)
#define SLIPIF_THREAD_PRIO            osPriorityHigh
#define DEFAULT_THREAD_STACKSIZE      (512u)
#define DEFAULT_THREAD_PRIO             osPriorityHigh

//==============================================================================================================
// DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
// NETCONN_UDP. The queue size value itself is platform-dependent, but is passed
// to sys_mbox_new() when the recvmbox is created.
// 消息邮箱大小,每个邮箱内容占用6个字节,指针+长度。
//==============================================================================================================
#define TCPIP_MBOX_SIZE               (6u)
#define DEFAULT_UDP_RECVMBOX_SIZE       (6u)
#define DEFAULT_TCP_RECVMBOX_SIZE       (6u)
#define DEFAULT_ACCEPTMBOX_SIZE         (6u)

//==============================================================================================================
// LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT
// options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set
// in seconds. (does not require sockets.c, and will affect tcp.c)
//
// Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing
// 保活机制的参数,满足 RFC1122 标准,不要修改,除非你清楚地知道你在做什么。
// 实际保活机制的默认参数,保活检测的时间间隔太长,如果需要更快发现连接问题,需要缩短保活时间参数。
//
// LWIP_TCP_KEEPALIVE == 1:开启保活机制自定义参数。
// 如果 TCP_KEEPIDLE_DEFAULT 时间内没有数据交互,则发起保活探测(默认值为 7200000ms=2小时)。
// 每 TCP_KEEPINTVL_DEFAULT 时间发送一次保活探测(默认值为 75000 = 75s)。
// TCP_KEEPCNT_DEFAULT:保活探测发送的次数
//==============================================================================================================
#define LWIP_TCP_KEEPALIVE            (1u)
#define TCP_KEEPIDLE_DEFAULT            (90000u)
#define TCP_KEEPINTVL_DEFAULT         (5000u)
#define TCP_KEEPCNT_DEFAULT             (3u)

//==============================================================================================================
// LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
// SO_SNDTIMEO processing.
// 注意,调用 netconn_write 函数发送数据,是不能开启发送超时的。
//       如果开启 LWIP_SO_SNDTIMEO == 1,并且 tcp_conn->send_timeout != 0,那么会返回参数错误。
//==============================================================================================================
#define LWIP_SO_SNDTIMEO                (0u)

//==============================================================================================================
// LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and
// SO_RCVTIMEO processing.
// 接收超时定义,可以用作心跳超时检测,如果在超时时间内没有收到心跳包,表示连接异常。
// 开启 LWIP_SO_RCVTIMEO == 1,需要设置 tcp_conn->recv_timeout 接收超时时间,单位ms。
//==============================================================================================================
#define LWIP_SO_RCVTIMEO                (1u)

//==============================================================================================================
// LWIP_TCPIP_CORE_LOCKING
// Creates a global mutex that is held during TCPIP thread operations.
// Can be locked by client code to perform lwIP operations without changing
// into TCPIP thread using callbacks. See LOCK_TCPIP_CORE() and
// UNLOCK_TCPIP_CORE().
// Your system should provide mutexes supporting priority inversion to use this.
// 内核互斥锁开关,必须开启。
//==============================================================================================================
#define LWIP_TCPIP_CORE_LOCKING         1

//==============================================================================================================
// LWIP_TCPIP_CORE_LOCKING_INPUT: when LWIP_TCPIP_CORE_LOCKING is enabled,
// this lets tcpip_input() grab the mutex for input packets as well,
// instead of allocating a message and passing it to tcpip_thread.
//
// ATTENTION: this does not work when tcpip_input() is called from
// interrupt context!
// tcpip_input() 同样使用竞争内核互斥锁的方式,替代申请发送消息给tcpip_thread。
// 注意:如果开启输入互斥锁,tcpip_input() 不能在中断中调用!
// 测试结果:在多任务并发的时候,开启 LWIP_TCPIP_CORE_LOCKING_INPUT == 1,可以大幅提高通信速率,特别是稳定性。
//         开启前,多任务并发时,通信速率低且不稳定,发送函数 netconn_write 会阻塞死发送任务。
//         开启后,多任务并发时,通信速率高且稳定,发送函数 netconn_write 不会阻塞死发送任务。
//==============================================================================================================
#define LWIP_TCPIP_CORE_LOCKING_INPUT   (1u)

//==============================================================================================================
// SYS_LIGHTWEIGHT_PROT==1: enable inter-task protection (and task-vs-interrupt
// protection) for certain critical regions during buffer allocation, deallocation
// and memory allocation and deallocation.
// ATTENTION: This is required when using lwIP from more than one context! If
// you disable this, you must be sure what you are doing!
//==============================================================================================================
#define SYS_LIGHTWEIGHT_PROT            (1u)

//==============================================================================================================
//LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per
// thread calling socket/netconn functions instead of allocating one
// semaphore per netconn (and per select etc.)
// ATTENTION: a thread-local semaphore for API calls is needed:
// - LWIP_NETCONN_THREAD_SEM_GET() returning a sys_sem_t*
// - LWIP_NETCONN_THREAD_SEM_ALLOC() creating the semaphore
// - LWIP_NETCONN_THREAD_SEM_FREE() freeing the semaphore
// The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup().
// Ports may call these for threads created with sys_thread_new().
// 测试结果:开启该宏,编译会报错,目前没有深入分析。
//==============================================================================================================
#define LWIP_NETCONN_SEM_PER_THREAD (0u)



//==============================================================================================================
// 这里是调试相关
// 压力测试,不要打开调试信息输出,输出的信息量太大了!
//==============================================================================================================
/*
extern void print( const INT8U* format, ... );

#ifndef   LWIP_PLATFORM_DIAG
#define   LWIP_PLATFORM_DIAG(x)   print x
#endif

#define   U8_F                  "c"
#define   S8_F                  "c"
#define   X8_F                  "x"
#define   U16_F                   "u"
#define   S16_F                   "d"
#define   X16_F                   "x"
#define   U32_F                   "u"
#define   S32_F                   "d"
#define   X32_F                   "x"

#define   LWIP_DEBUG            (1u)

//#define   NETIF_DEBUG         LWIP_DBG_ON
//#define   API_MSG_DEBUG       LWIP_DBG_ON
//#define   MEM_DEBUG         LWIP_DBG_ON
//#define   MEMP_DEBUG          LWIP_DBG_ON
//#define   SYS_DEBUG         LWIP_DBG_ON
//#define   TCP_DEBUG         LWIP_DBG_ON
//#define   TCP_INPUT_DEBUG   LWIP_DBG_ON
//#define   TCP_FR_DEBUG      LWIP_DBG_ON
//#define   TCP_RTO_DEBUG       LWIP_DBG_ON
//#define   TCP_CWND_DEBUG      LWIP_DBG_ON
//#define   TCP_WND_DEBUG       LWIP_DBG_ON
    #define   TCP_OUTPUT_DEBUG    LWIP_DBG_ON
//#define   TCP_RST_DEBUG       LWIP_DBG_ON
//#define   TCP_QLEN_DEBUG      LWIP_DBG_ON
*/



//==============================================================================================================
// 其他宏定义
// CubeMX 生成,没有做改动的部分。
//==============================================================================================================
/*----- Value in opt.h for RECV_BUFSIZE_DEFAULT: INT_MAX -----*/
#define RECV_BUFSIZE_DEFAULT      2000000000
/*----- Value in opt.h for LWIP_STATS: 1 -----*/
#define LWIP_STATS                  0
/*----- Value in opt.h for CHECKSUM_GEN_IP: 1 -----*/
#define CHECKSUM_GEN_IP             0
/*----- Value in opt.h for CHECKSUM_GEN_UDP: 1 -----*/
#define CHECKSUM_GEN_UDP            0
/*----- Value in opt.h for CHECKSUM_GEN_TCP: 1 -----*/
#define CHECKSUM_GEN_TCP            0
/*----- Value in opt.h for CHECKSUM_GEN_ICMP: 1 -----*/
#define CHECKSUM_GEN_ICMP         0
/*----- Value in opt.h for CHECKSUM_GEN_ICMP6: 1 -----*/
#define CHECKSUM_GEN_ICMP6          0
/*----- Value in opt.h for CHECKSUM_CHECK_IP: 1 -----*/
#define CHECKSUM_CHECK_IP         0
/*----- Value in opt.h for CHECKSUM_CHECK_UDP: 1 -----*/
#define CHECKSUM_CHECK_UDP          0
/*----- Value in opt.h for CHECKSUM_CHECK_TCP: 1 -----*/
#define CHECKSUM_CHECK_TCP          0
/*----- Value in opt.h for CHECKSUM_CHECK_ICMP: 1 -----*/
#define CHECKSUM_CHECK_ICMP         0
/*----- Value in opt.h for CHECKSUM_CHECK_ICMP6: 1 -----*/
#define CHECKSUM_CHECK_ICMP6      0
/*-----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */



#ifdef __cplusplus
}
#endif

#endif /*__LWIPOPTS__H_H */


//================================分割线================================================================================
LWIP V2.0.3, 以上是根据个人的理解,以及反复测试得出的配置,占用内存比较大,但数据速率可以到50Mbps以上,还比较稳定。
在IAR下,只能低优先级优化,不要开中、高优先级优化。工程由 CubeMX 自动生成。

棋间卒 发表于 2019-1-28 10:26:52

2.0.3有bug,用最新的2.1.3,比较好用

guxingganyue 发表于 2019-1-29 22:40:47

saccapanna 发表于 2019-1-28 09:00
/**
******************************************************************************
* File Nam ...

谢谢分享,,,我和我的比较一下看看区别

guxingganyue 发表于 2019-1-29 22:50:57

棋间卒 发表于 2019-1-28 10:26
2.0.3有bug,用最新的2.1.3,比较好用

你用的是RAW的api吧,听说这些api在2.1.2中升级了许多,很好用了。。

我用ucos+lwip 2.1.2测试,tcp client容易出现连接断开重连后无法再次成功连接到服务器的问题,仿真程序一直在 netconn_connect 重连,18秒后超时(即使前面加了tcp_clientconn->recv_timeout = 1000;也没有用,必须等到18秒超时后)该函数才返回。debug提示no pcb,wireshark监视确实没有连接server数据包。我修改了lwipopts文件,也无法解决这个问题,换2.0.3后就好了。

注:我的2.1.2的tcp server也出现过no pcb问题,但是加入了超时控制后就没出现了。。。

请问我的2.1.2的tcp client大数据量长时间(12小时,100ms发送一次数据)测试,我主动断开server后,为啥有的client就再也无法连接到server了呢?同时测试5个机器,有1个无法重连,其他4个却可以正常重连成功。谢谢先

棋间卒 发表于 2019-2-12 16:55:25

guxingganyue 发表于 2019-1-29 22:50
你用的是RAW的api吧,听说这些api在2.1.2中升级了许多,很好用了。。

我用ucos+lwip 2.1.2测试,tcp cli ...

不是,我用的socket接口

guxingganyue 发表于 2019-2-16 14:04:41

棋间卒 发表于 2019-2-12 16:55
不是,我用的socket接口

你发现的2.0.3有什么bug呢?2.1.2的client你没发现问题?

guxingganyue 发表于 2019-2-18 19:22:05

saccapanna 发表于 2019-1-28 09:00
/**
******************************************************************************
* File Nam ...

今天我测试了下你的配置,在lwip 2.0.3上,但是加入下面的宏后,lwip ping都无法ping通了【当然其他的业务也都不工作了】,去掉后就好了,这是为啥呢?
#define LWIP_TCPIP_CORE_LOCKING_INPUT   (1u)

注:tcpip_input() 没有在中断中调用!os用的是ucos-ii


saccapanna 发表于 2019-2-19 13:49:56

guxingganyue 发表于 2019-2-18 19:22
今天我测试了下你的配置,在lwip 2.0.3上,但是加入下面的宏后,lwip ping都无法ping通了【当然其他的业 ...

这个要深入分析代码了,可能是互斥锁实现上的问题。不知道是否与操作系统的互斥信号量有关,我用的是FreeRTOS ,CubeMX生成的移植,然后修改了配置。

guxingganyue 发表于 2019-2-19 22:00:52

saccapanna 发表于 2019-2-19 13:49
这个要深入分析代码了,可能是互斥锁实现上的问题。不知道是否与操作系统的互斥信号量有关,我用的是Free ...

嗯,谢谢,应该和OS有关系,有时间我仿真跟踪下看看哪里出问题了

KongQuan 发表于 2019-3-7 14:26:35

mark, 准备在stm32f407上用lwIP

AppTurtle 发表于 2019-3-7 23:45:59

LWIP 3K设备平均运行3年了,没发现问题

guxingganyue 发表于 2019-3-8 08:28:53

AppTurtle 发表于 2019-3-7 23:45
LWIP 3K设备平均运行3年了,没发现问题

lwip 2.1.2?有OS没

kinsno 发表于 2019-8-5 10:59:10

saccapanna 发表于 2019-1-23 20:06
做连接异常监测啊,如果不能恢复连接就复位,目前来看LWIP还是挺稳定的,但的确也有bug。比如发送阻塞死 ...

最近搞了一个MQTT client
基于LWIP,。
我们领导打算让我对网络进行泛攻。。
ARP攻击,TCP攻击,反正就是各种攻击,我心想,路由器都不一定顶得住咧,这个LWIP能顶得住?
想了解一哈,你原来说的压力测试和异常监测,是有专用的软件吗,或专用的名词吗,我去学习一下。。感觉在TCP方面还是菜鸟啊。



saccapanna 发表于 2019-8-5 13:41:11

kinsno 发表于 2019-8-5 10:59
最近搞了一个MQTT client
基于LWIP,。
我们领导打算让我对网络进行泛攻。。


设备做客户端,电脑做服务端,电脑发数据,客户端返回相同数据。我说的压力测试基本是功能测试,是用电脑快速灌大数据包测试,运行了十多天。分两种,一种是玩命灌数据,不管数据返回是否正常,客户端不死机就好,另外一种是保证返回数据正常情况下,最大速率灌,我测试用的(48Mbps左右,开了4个连接)。另外异常处理,是要开始包发送接受超时,接收返回异常,要根据情况处理,我处理的方式是,与内存相关的异常,我都直接复位系统,其他的重建连接。值得注意的是,内存开小了,发送有阻塞死任务的情况,也要处理。总之各种异常要能恢复,设备在现场没人去断电重启的。你说的用仪器测试,我也听说有这种方法,但公司没有专门的仪器,就没法测试。ARP欺骗,在路由上绑定IP和MAC,其他的攻击暂时没考虑过。

kinsno 发表于 2019-8-5 14:16:58

saccapanna 发表于 2019-8-5 13:41
设备做客户端,电脑做服务端,电脑发数据,客户端返回相同数据。我说的压力测试基本是功能测试,是用电脑 ...

懂了,你说的压力测试,就是数据大一点来不停的发送,看看会不会死机崩溃。。上午我也了解了一下,实际上还有好多攻击和测试。。下个月要专门研究这些网络层报文的保护。。

ljq77402 发表于 2019-8-26 17:20:14

    tcp_serverconn->recv_timeout=200;               //---------这个非常重要哦

    err=netconn_accept(tcp_serverconn, &newconn);

请问加入超时之后,netconn_accept是不是变成非堵塞型的了?等200个时间单位之后,执行后面的程序,还有这个200的时间单位是秒还是毫秒?

guxingganyue 发表于 2019-8-29 08:53:30

ljq77402 发表于 2019-8-26 17:20
tcp_serverconn->recv_timeout=200;               //---------这个非常重要哦

    err=netconn_a ...

1、netconn_accept是变成非堵塞型的了,如果没有连接,这样就可以执行后面的netconn_delete(tcp_serverconn);这样server就不会出现卡死,client连接不成功的现象了
2、ms

ljq77402 发表于 2019-9-9 11:33:22

新建连接放在while(1)里面确实,可以防止其它连接连上来,
while (1)
{
    tcp_serverconn = netconn_new(NETCONN_TCP);      //新建一个netconn连接
    netconn_bind(tcp_serverconn, IP_ADDR_ANY, 12345); //绑定ip和端口号
    netconn_listen(tcp_serverconn);                   //开始监听
。。。。。。。。。。。。。

我试了,新建一个连接,用来侦听,当有连接连上来后关闭侦听的连接,不删除,TCP服务出错的的话,再重新把侦听连接置于侦听状态就出问题了,

ljq77402 发表于 2019-9-9 11:40:53

void StartModBusTcp(void const * argument)
{
struct netconn *conn, *newconn;
err_t err;
/* Create a new TCP connection handle */
conn = netconn_new(NETCONN_TCP);

netconn_bind(conn, NULL, 502); //modbusTcp 502

/* Put the connection into LISTEN state */
//netconn_listen(conn);

printf("task modbus tcp ok!\r\n"); //for debug

   while(1)
{

       /* Put the connection into LISTEN state */
   netconn_listen(conn);

      
    err = netconn_accept(conn,&newconn);//等待新的TCP连接,如果有
    //printf("netconn_accept_err:%d\r\n",err);
          if(err == ERR_OK)
                {
                        netconn_close(conn);//关闭侦听的连接,防止其它连接再连上来
                        ModbusTCP_server(newconn);//里面带while(1) 如果连接中断或者规定时间内没收到 数据就跳出来
                }
    netconn_close(newconn);         //关闭正在通讯的连接       
    netconn_delete(newconn);    //删除之前通讯的连接
       
}

}

调用了netconn_close(conn);//关闭侦听的连接,防止其它连接再连上来   
之后, err = netconn_accept(conn,&newconn); 返回 -15,(ERR_CLSD),表明侦听的连接已经处于关闭状态了,,netconn_listen(conn);这个函数视乎没有把已经关闭的连接重新置于侦听状态!除了删除,再新建一个连接,有没办法再重新使用已经关闭的连接呢?视乎netconn 的API中也没找到合适的函数

aozima 发表于 2019-9-9 11:50:39

楼主的问题应该是和 SO_REUSEADDR 相关吧

guxingganyue 发表于 2019-9-9 13:06:29

ljq77402 发表于 2019-9-9 11:40
void StartModBusTcp(void const * argument)
{
struct netconn *conn, *newconn;


使用socketopt函数,设置 SO_REUSEADDR   应该可以,你试试

ljq77402 发表于 2019-9-9 17:59:57

改了下TCP侦听队列大小为 1,能实现只有一个连接能连上来,测试暂时没发现错误,效率稍高些,

#dfine TCP_LISTEN_BACKLOG1
netconn_listen 改为netconn_listen_with_backlog(conn,1);/


void StartModBusTcp(void const * argument)
{
struct netconn *conn, *newconn;
err_t err;
/* Create a new TCP connection handle */
conn = netconn_new(NETCONN_TCP);

netconn_bind(conn, NULL, 502); //modbusTcp 502

        /* Put the connection into LISTEN state */
//netconn_listen(conn);   //这里设置TCP_LISTEN_BACKLOG=0, TCP_DEFAULT_LISTEN_BACKLOG == 0xFF连接队列255个
netconn_listen_with_backlog(conn,1);//TCP_LISTEN_BACKLOG == 1,连接队列为1,

LWIP_DEBUGF( MODBUS_TCP_DEBUG,("task modbus tcp ok!\r\n"));
   while(1)
{
         
   err = netconn_accept(conn,&newconn);//等待新的TCP连接,阻塞函数
           LWIP_DEBUGF( MODBUS_TCP_DEBUG,("netconn_accept_err:%d\r\n",err) );
       
          if(err == ERR_OK)
                {
                        showConn_SoureIP_Port(newconn);
                        ModbusTCP_server(newconn);
                       
                       
                  err = netconn_close(newconn);                
                  LWIP_DEBUGF( MODBUS_TCP_DEBUG,("close communication netconn err:%d\r\n",err));
                }
                       
      err = netconn_delete(newconn);
                LWIP_DEBUGF( MODBUS_TCP_DEBUG,("delete communication netconn err:%d\r\n",err));        

}

}

guxingganyue 发表于 2019-9-10 10:33:53

ljq77402 发表于 2019-9-9 17:59
改了下TCP侦听队列大小为 1,能实现只有一个连接能连上来,测试暂时没发现错误,效率稍高些,

#dfine TCP_ ...

刚看了下我的TCP_DEFAULT_LISTEN_BACKLOG也是1
直接用 netconn_listen就行,不用改,具体见下图



这个宏默认值为255,太大了

页: [1]
查看完整版本: Lwip 2.1.2用netconn_accept建立的server被close,重建后client重连失败