CH395 tcp客户端 热拔插

CH395做tcp客户端,实现网线拔掉后tcp断开,网线插上后tcp连接。

目前提供三种思路:

芯片测试版本:0x49,测试工具:TCPIPDebug做服务器

1.第一种思路

(1)代码:(在CH395的tcp_client例程的超时终端和PHY_Change中断中加上下面的代码即可)

 1 u8 sock_sta[2];
 2 u8 i ;
 3 if(init_status & GINT_STAT_PHY_CHANGE)                      /* 产生PHY改变中断*/
 4 {
 5     CH395CMDGetSocketStatus(0,sock_sta);                   /*查询socket状态*/
 6     printf("SOCK-sta:%x %x\r\n",sock_sta[0],sock_sta[1]);
 7     
 8     if(sock_sta[0] == 0x05 && sock_sta[1] == 0x04)       /*socket已打开且tcp已建立*/
 9     {
10         i = CH395CloseSocket(0);
11         mStopIfError(i);
12     }
13 }
14 
15 
16 if(sock_int_socket & SINT_STAT_TIM_OUT)                           /* 超时中断 */
17 {
18     printf("超时中断 \n");
19     i = CH395OpenSocket(sockindex);        /* 打开socket 0 */
20     mStopIfError(i);               /* 检查是否成功 */
21     i = CH395TCPConnect(sockindex);
22     mStopIfError(i);
23 }

 

(2)原理:

①拔插网线都会产生相同的PHY_Change中断,如何判断此时是拔网线的动作还是插网线的动作?在tcp模式下,可以通过查socket状态来区别(当然也可以直接通过查询phy的协商状态来判断),如上程序,当网线插上时,由于是tcp客户端模式,所以395会发送SYN握手,此时socket的状态为SYN发送态(上述代码没写,这个不需要),当tcp建立完成后,socket的状态改为TCP连接建立态;当tcp建立成功后,此时我们拔掉网线,进入phy_change中断,查到socket的状态为连接态,执行关闭socket的函数。(PS:关于tcp的连接状态参考手册5.22章节)

②由于执行了关闭socket的函数,所以395会发送FIN挥手包以此希望断开此次tcp连接,但是由于此时网线被拔掉,导致FIN包不能正常发包。因此,此时如果我们插上网线,可以看到395会立马发出之前想要发但没能发出去的FIN包,此时服务端并不会执行正常的挥手,而是直接发送RST包复位到之前的tcp连接,之后395检测到tcp断开异常,因此会产生超时中断,我们在超时中断中重新打开socket和执行tcp连接函数即可实现功能。

注:抓包如下,192.168.1.112是395的ip,192.168.1.100是PC服务器的ip

 

2.第二种思路,不采用超时中断的方式,全在放在phy_change中断中处理。但由于395的机制,一旦进入超时中断或断开中断,都会默认关闭该socket,所以为了以防意外情况导致tcp连接断掉,一般都建议在这两个中断里加上打开socket的操作以保证异常发生后还能继续实现tcp通信,所以第二种方式不做推荐,在此就不多赘述。

 

3.第三种思路,借助keeplive功能实现。代码如下,根据手册要求,tcp客户端模式下需要在tcp连接成功后开启此功能,keeplive的空闲时间为5秒、超时时间为3秒和重试次数为200(参考手册5.56~5.59章节)

 1     if(sock_int_socket & SINT_STAT_CONNECT)                          /* 连接中断,仅在TCP模式下有效*/
 2     {
 3         printf("连接中断 \n");
 4         CH395SetKeepLive(sockindex,1);                                 /*打开KEEPALIVE保活定时器*/
 5     }
 6 
 7 
 8    if(sock_int_socket & SINT_STAT_TIM_OUT)                           /* 超时中断 */
 9    {
10         printf("超时中断 \n");
11         i = CH395OpenSocket(sockindex);                                          /* 打开socket 0 */
12         mStopIfError(i);/* 检查是否成功 */
13         i = CH395TCPConnect(sockindex);
14         mStopIfError(i);
15    }

原理:

tcp连接建立成功后,由于实际应用中,可能并不是时时刻刻都有数据传输,此时一般会开启keeplive功能来实现保活。如下,tcp连接建立后,当20ms无数据传输时,395会发送keep-alive包,服务器收到会回复相应的ack包。

 

此时拔掉网线,当网线再次插上,395会尝试发送keeplive包,此时服务器会直接将将连接RST掉,导致进入超时中断,从而重新打开open和建立tcp连接

 

总结:推荐第一种方式,如有更好的方法可以评论交流

posted on 2024-09-26 09:36  Lqqq123  阅读(55)  评论(0编辑  收藏  举报

导航