关于TCP或FTP异常断开的处理方法总结

  最近在项目中遇到一些小小的问题,犯过的错希望不要犯二次。我Linux环境下开启一个TCP服务和FTP客户端用来升级系统,正常情况下是没任何差错的,如果断网(拔网线)或者PC端升级软件(QT软件)崩溃(强行退出),系统就会出现问题,

  流程有2个,一个是FTP下载过程,一个是Flash写入过程,都涉及进度值的上传,即无时无刻都在调用write函数,并且进度函数的返回值是不处理的,也是没有任何函数来处理检测此函数是否正常运行的,主要是没法处理接收。

  FTP下载CURL设置: 进度函数部分

  TCP在正常网络下是“三次握手,四次挥手”,服务器和客户机分别正常退出处理是没什么问题的。

  一、如果突然断网了,PC端TCP客户机不会发任何信息,可能出现的问题有:

    ①此时如果还处于TCP命令交互过程,可添加keepalive机制(只开启设置当前套接字的keepalive属性),保证规定时间内没有回响可关闭套接字,等待下一次连接。注意不能更改Linux整个系统的keepalive值

       系统keepalive值可通过sysctl -a 或者 sysctl -a  |grep tcp_keepalive*   查看

      

      当前tcp套接字keepalive设置代码:

    

    ②此时如果处于FTP下载过程中,curl库会一直卡死在那里,无法自动退出来(curl设计机制问题,没法更改),但是进度函数里面write不会报错(断网情况下返回值不为-1),导致此更新进程模块废掉,只能重启,解决办法可以添加curl下载超时限制CURLOPT_TIMEOUT,该延时表示多久到了文件还没有下载完成curl就会自动断开重新连接下载,由于断网,此时连接超时(CURLOPT_CONNECTTIMEOUT)将会自动退出,从而可以正常处理,程序如下

    curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 120);

此语句缺点就是不管多大文件,只给你120S的下载时间,如果文件过大,120S下载不完,那么一直死循环下载会出问题,所以不到万不得已不要使用,由于项目实际文件最大的才6M多点,一般正常网络情况下30s内可解决战斗,遇到网络不好的可能时间长点,

此延时时间设置太大也不行,没有及时性,都出问题了,你不可能让客户等很长时间吧?客户还以为更新失败成砖了,直接报废处理了。

    ③此时处于写入过程中时。进度函数中write也不会出错,也没法接收,就让它写完再在FTP连接的过程中失败退出吧。

二、若果上位机突然崩溃了,此时window 系统会回收套接字,给tcp服务器端发送一个RST信号,此时Linux下面处于集中情况:

  ①此时如果还处于TCP命令交互过程中,与上一样,有keepalive机制,规定时间内可以自动断开,等待下一次连接。

  ②此时如果处于FTP下载过程中,由于进度函数不断被调用,不断循环(curl设置1S时间调用进度函数一次)调用write函数上发数据,上面崩溃时也会不断被调用,第一次调用write会返回-1,第二次再调用write就会阻塞卡死在write这里(这个地方吃了大亏),不得不吐槽curl库,既然FTP服务器端都没了,出问题了,客户端怎么还是不停的调用进度函数?上面提到了curl中是不涉及处理进度函数返回值的,管你是不是出错,这时候没办法啊,既然出错了,我的要赶紧退到初始调用FTP下载到的地方吧?怎么办?在函数之间进行跳转的恐怕只有setjmp()  / longjmp()吧?C语言错误异常跳转特殊函数,与函数AR地址相关的,比goto还厉害的语句。

在最最开始顶层的地方设置如下: 

AbnormalFlag = setjmp(Ftpdown_jb);
if(AbnormalFlag == 0 )
{
/* null */
}
else if(AbnormalFlag == 1 )
{
 Enter setjmp Ftpdown_jb abnormar  
FileSuccessAllFlag = 0;
goto end;
}
else
{
/* null */
}

ret = FtpDownload(***);

然后在进度函数中write中写入如下

ret = write(G_sock_c,SendBuff,ret);
if(ret < 0)
{
     **** 
   longjmp(Ftpdown_jb,1);
}

write第一次出错,保证能退出来,实现函数隔层之间的的跳转,然后释放当前套接字,等待下一次连接。

  ③此时处于flash过程与上同理处理。

好了,写了这么多,有不严谨之处还请指教。

  

原文地址:https://www.cnblogs.com/YWX888/p/11057957.html

时间: 2024-10-28 07:22:40

关于TCP或FTP异常断开的处理方法总结的相关文章

socket选项自带的TCP异常断开检测

TCP异常断开是指在突然断电,直接拔网线等等情况下,如果通信双方没有进行数据发送通信等处理的时候,无法获知连接已经断开的情况. 在通常的情况下,为了使得socket通信不受操作系统的限制,需要自己在应用层实现心跳包机制,来检查异常断开的情况,一般的方式就是服务器在一段时间没有收到客户端数据包时,定时发包,然后客户端回应,如果已经出现异常断开则服务器接收会返回错误,而客户端在指定时间内没有收到数据包,则主动向服务器发包,得到错误就说明断开.诸如此类的方式就是自己实现的心跳包机制. 但操作系统本身也

(转)TCP连接异常断开检测

TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现.某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接.下面介绍一种方法来检测这种异常断开的情况 TAG: TCP连接异常断开  TCP断链 TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现.某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接.下面介绍一种方法来检测这种异常断开的情况 1) 在TCP协议中提供了KEEPA

Socket .net MVC 的配置 包括异常断开

解决问题: 1. Socket 的异常断开 2. 部署在IIS程序池上的程序回收导致 端口占用,对象资源却已经释放的BUG SocketHelper 类   inOptionValues .net框架中用于检测连接的客户端 检测时间(默认2小时)   或者自己写个心跳包(客户端和服务端用规定协议) 1 #region 变量 2 3 //服务器监听socket 4 public static Socket listener = null; 5 6 /// <summary> 7 /// 连接列表

TCP/IP 四次断开

TCP/IP 四次断开详细过程: 四次断开名词定义: ACK :TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1 SYN(SYNchronization) :在连接建立时用来同步序号,当SYN=1而ACK=0时,表明这是一个连接请求报文,对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此,  SYN置1就表示这是一个连接请求或连接接受报文. Seq:序号,4字节,范围为0^32-1^32,共4284967296,达到时重新开始计算 四次断开过

TCP四次挥手断开连接详解

TCP四次挥手. 数据传输结束后,通信的双方都可释放连接.现在A和B都处于ESTABLISHED状态.A的应用程序先向TCP发出连接释放报文段,主动关闭TCP连接.A把连接释放报文段的首部FIN置为1,序号seq=u,它等于前面已传送过的数据的最后一个字节的序号加1.这时A进入FIN-WAIT-1状态,等待B的确认. B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v,等于B前面已传送过的数据的最后一个字节的序号加1.然后B就进入CLOSE-WAIT状态.TCP

TCP连接突然断开的处理方法

TCP是因特网中的传输层协议,使用三次握手协议建立连接,下面是TCP建立连接的全过程. TCP断开连接的过程:TCP四次挥手. TCP/IP 协议簇分层结构 数据链路层主要负责处理传输媒介等众多的物理接口细节: 网络层负责处理数据分组在网络中的活动,包括上层数据报文的分割.选路 等: 传输层则负责为两台主机提供端到端的通信: 应用层将负责处理应用程序的特定细节. 其中,IP 协议是网络层的核心协议,用来提供不可靠.无连接的数据传递服务:而 TCP 协议则处于传输层,其基于不可靠无连接的 IP 协

TCP协议详解(TCP建立连接与断开连接)

TCP是面向连接的.可靠的进程到进程通信的协议.它提供的是全双工(双向可传输)的服务,每个TCP都有发送缓存和接受缓存,用来临时存储数据. 1.TCP报文段:TCP把若干个字节构成一个分组,称为报文段(segment).TCP报文段封装在IP数据报中,TCP报文段的首部格式如下图所示: 首部长度为20~60个字节,一下是各个字段的含义:①:源端口号:它是16位字段,为发送发进程对应的端口号:②:目标端口号:它是16位字段,对应的是接收端的进程,接收端收到数据段后,根据这个端口号来确定把数据送给哪

TCP/IP异步通讯服务端实现方法

近期做了个TCP/IP异步通讯服务端实现方法,也是在网上胡乱搜索,然找了个自认为比较好的,然后封装一下,供后面自个使用,也供大家参考,如有不好的地方,欢迎指正,谢谢! 下面说一下这个方法里面的几个知识点: 1.托管 这个东西真心好用,虽然不知道具体怎么弄的,托管可以实现一个对象中的方法交由其他对象实现,而且可以同时触发多个方法,组件的触发函数就是由托管实现的,具体实现如下: 先声明一个托管的方法类型 public delegate void RecieveMsg(string IP_addr,

(转)Java ConcurrentModificationException异常原因和解决方法

转自 http://www.cnblogs.com/dolphin0520/p/3933551.html 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.util.ConcurrentModificationException异常.下面我们就来讨论以下这个异常出现的原因以及解决办法. 以下是本文目录大纲: 一.ConcurrentModificationException异常出现的原因 二.在单线程环境下的解决办法 三.在多线程环境下的解