Microchip
直播中

陈燕

7年用户 1060经验值
私信 关注
[问答]

未使用keep-alive设置关闭的套接字

目前我有麻烦使用HTTP(S)连接。编译器:XC32 1.44 Health:V2.04(V2.05在这方面没有太大的改变)。我使用NETSIPRESS层打开套接字,直到打开和关闭几个插槽为止。它看起来好像我的插座已经用完了,所以我开始挖一点。有一件事发生了:它看起来像我可以。请输入一个套接字,但对NETAXPROSSOCKIStiON连接的查询从未返回true。在调试之后,我发现我的套接字确实耗尽了。但是NETA PrimeSoCKOPENT不会返回NETApPrimeSimuldIsSub,但有些数字表明一切都很好。原因是:这是不正确的。TrANHANDLE是一个无符号的16位类型,而NETSpRySuxIDIdSoCub被定义为(-1)。这意味着它被签署了。因此,比较是(65535==1)……我还想指出,在一个错误的情况下,TrANHANDLE将被设置为无效的SuthSoT(从TCP。H)。不幸的是,NETA PrimeSimuldIsSub是单独定义的。在我看来,NETSyPrimeValuiSoSub应该定义为无效的套接字。至少两个都应该有一个共同的父定义。但是回到原来的问题(套接字耗尽):NETAXPROSSOCKOSEND调用TCPIPUTCPY关闭,调用TyTCPDISCONTION。由于某些原因,状态机处于状态TCPIPpTCPYSTATEYLASSTARACK,并与OXTCPHSDENTHOK断开连接,但实际上并没有关闭套接字。NETXPRES-SOCKIT处理程序被释放,但实际的TCP套接字保持打开状态!我将我的代码与TCPIpHelocver示例进行了比较,结果如下:这可能是一个错误:当在请求中设置“连接:保持生存”时,TCP套接字不会被NETApPrimeSockCocket关闭。只有在保持活动设置超时之后,套接字才会关闭。我认为这不是正确的行为。当我显式关闭套接字时,我只是希望套接字立即关闭。当我关闭套接字时,无论如何我不能重新使用连接,因为我失去了所有的socket句柄。作为一种解决办法,我试图降低保持生存超时,但这并没有降低超时,直到套接字被释放。

以上来自于百度翻译


      以下为原文

    I am currently having trouble to use HTTP(S) connections.
Compiler: xc32 1.44
HARMony: v2.04 (the v2.05 did not change much in that respect)

I use the NET_PRES layer to open the socket and it works until I open and close a few more sockets.
It looked like I was running out of sockets, so I startet to dig a bit.

One thing that came up: it looked like I could open a socket, but the query to NET_PRES_SocketIsConnected never returned true.
After debugging, I discovered that my sockets are indeed depleted. But NET_PRES_SocketOpen would not return NET_PRES_INVALID_SOCKET but some number that idicates that everything went fine.
The reason:

net_pres.c
line 299:
        if (sNetPresSockets[sockIndex].transHandle == NET_PRES_INVALID_SOCKET)

This is not correct. transHandle is a unsigned 16Bit type while NET_PRES_INVALID_SOCKET is defined to (-1). That means it is signed. So the comparison is down to (65535 == -1)...
I also want to point out that, in an error case, transHandle will be set to INVALID_SOCKET (from tcp.h). Unfortunately NET_PRES_INVALID_SOCKET is separately defined. In my opinion NET_PRES_INVALID_SOCKET should be defined to INVALID_SOCKET. At least both should have a common parent define.

But back to the original problem (running out of sockets):
NET_PRES_SocketClose calls TCPIP_TCP_Close which calls _TCPDisconnect. The state machine is in state TCPIP_TCP_STATE_LAST_ACK for some reason and disconnect leaves with _TCP_SEND_OK but is not actually closing the socket. The NET_PRES-Socket-Handler is freed, but the actual TCP Socket stays open!

I compared my code to the tcpip_client example and it came down to the following, which might be a bug:
When "Connection: keep-alive" is set in the request, the tcp-socket is not closed with NET_PRES_SocketClose. Only after the timeout of the keep alive settings, the socket is closed.
I do not think this is a correct behaviour. When I explicitly close the socket, I just expect the socket to be closed immediately. When I close the socket, I cannot re-use the connection anyway, because I lost all the handles to the socket.


As a workaround, I tried to lower the keep-alive timeout with

    TCP_OPTION_KEEP_ALIVE_DATA keepAliveData;
    keepAliveData.keepAliveEnable = true;
    keepAliveData.keepAliveTmo = 500;
    keepAliveData.keepAliveUnackLim = 1;
    if(!NET_PRES_SocketOptionsSet(socket, TCP_OPTION_KEEP_ALIVE, &keepAliveData))
    {
         ....
    }

but that did not lower the timeout until the socket is freed.

回帖(3)

云达贞

2018-9-14 15:56:08
嗨,戴维,NeTeSpRePosialSudioSocket和ValuiSuthSocket之间存在差异的问题是显而易见的,它将被立即修复。我将查看保存活着的问题并让你知道我发现了什么。当你从你身边关闭套接字时,它应该转到TimeIsAuth/2MSL状态并等待,但这样做了。CUTE应该关闭的应用程序和NETYPRE。也许你可以试试TCPPIpTCPYMLSYTIMEOUT==0(它是通过MHC访问的),看看它是否解决了这个问题。无论如何,我会在我的身边看,看看我发现了什么。谢谢你挖掘这个并带来它。引发比较,作为一个临时解决方案,请更改定义NETApPrsixPosial.H::NETA PrimeSoCKDATA {} UTIT1616T TANSHANDLE;Tutn16LT TrSANDLE;并尝试一下。

以上来自于百度翻译


      以下为原文

    Hi David,
 
The issue with the discrepancy between the NET_PRES_INVALID_SOCKET and INVALID_SOCKET is obvious and it'll be fixed immediately.
I'll look into the KEEP ALIVE issue and let you know what I find.
When you close the socket from your side, it should go to TIME_WAIT/2MSL state and wait, but the socket should be closed for the app and NET_PRES.
Maybe you can give it a try with TCPIP_TCP_MSL_TIMEOUT == 0 (it is accessible through MHC) and see if it solved the issue.
Anyway, I'll look into it on my side and see what I find.
Thank you for digging into this and bringing it up.
 
 P.S. For the signed/unsigned comparison, as a temporary workaround, please change the definition net_pres_local.h::NET_PRES_SocketData{}
uint16_t transHandle;
to 
int16_t transHandle;
and give it a try.
举报

李郝荫

2018-9-14 16:13:47
嗨,Runad,你对2MSL的暗示非常好。当我将它设置为0时,套接字立即可用。我做了一些关于这个问题的阅读,看起来我对它有一些错误的期望。没问题,网络预处理器被释放了,并且只有在TimaEnter状态之后,Socket才关闭,以防止从下一个连接接收Pocket。这篇文章帮助我理解了:埃尔纳林奇看起来我必须处理这个状态。改变Trhandle类型似乎也起作用。至少到现在为止,我没有看到任何副作用。谢谢你的帮助,并关注所有的问题!

以上来自于百度翻译


      以下为原文

    Hi rainad,
 
your hint to 2MSL was very good. When I set it to 0, the sockets become available immediately. I did some reading about this matter and it looks like I had some wrong expectations about it.
It is OK, that the net-pres handler is freed and the socket ist closed only after the TIMA_WAIT state to prevent receiving pakets from the next connection.
This article helped me a lot to understand it: external Link
 
It looks like I have to deal with this state somehow.
 
Changing the transHandle type seems to work too. At least till now, I saw no side effects.
 
Thanks for the help and for looking into all the issues!
举报

云达贞

2018-9-14 16:27:26
嗨,戴维,很高兴听到它为你工作。TrhanDle类型应该是1616,它将在存储库中更新。通常MSL不应该是0,但是如果你只有几个插槽,你可以使用这个设置。谢谢你识别这个问题。

以上来自于百度翻译


      以下为原文

    Hi David,
 
Good to hear it's working for you.
The transHandle type should be int16_t and it will be updated in the repository.
The part with the 2MSL is the expected behavior. Normally the MSL shouldn't be 0 but if you have just few sockets you could use this setting.
Thanks for identifying the issue.
 
 
 
举报

更多回帖

发帖
×
20
完善资料,
赚取积分