delphi idtcpclient和idtcpserver的心跳包

最近有个项目需要用到socket通信,对于socket的网络异常处理(程序异常退出或者网络掉了)及重连纠结了好久,网上虽然有很多资料,但是都是从一个地方转过来的,不够详细,查了很久的资料才弄出来的,原来的出处给忘了。

环境:delphi7+indy控件(dephi7自带)     工作需要才用delphi7,建议使用delphi2007及以上版本,delphi2007里面带的indy控件版本是10.0,修复了很多以前的bug

使用心跳包的理由:(ps:以下理由是抄的,感觉意思和我当初的初衷是一样的)
有开发网络应用经历的人都知道,网络中的接收和发送数据都是使用WINDOWS中的SOCKET进行实现。但是如果此套接字已经断开,那发送数据和接收数据的时候就一定会有问题。可是如何判断这个套接字是否还可以使用呢?
  有人一定想到使用Send函数中的返回结果来进行判断。如果返回的长度和自己发送出去的长度一致,那就说明这个套接字是可用的,否则此套接字一定出现了问题。但是我们并不是无时无刻的发送数据呀。如何解决呢?
  其实TCP中已经为我们实现了一个叫做心跳的机制。如果你设置了心跳,那TCP就会在一定的时间(比如你设置的是3秒钟)内发送你设置的次数的心跳(比如说2次),并且此信息不会影响你自己定义的协议。
 
原理网上都有,就是使用setsockopt函数和WSAIoctl函数,网上光介绍了怎么使用心跳机制,没有说处理办法。设置好心跳后,TCP就会在一定的时间(比如你设置的是3秒钟)内发送你设置的次数的心跳(比如说2次),如果网络异常(程序异常退出或者网络掉了),心跳就会抛出一个错误异常,我们只要知道在哪儿捕获异常,就能知道网络情况以及何时进行重连了。
 
服务端的心跳处理(idtcpserver)
  //定义心跳常量
Const
  IOC_IN = $80000000;
  IOC_VENDOR = $18000000;
  IOC_out = $40000000;
  SIO_KEEPALIVE_VALS = IOC_IN or IOC_VENDOR or 4;
  DATA_BUFSIZE = 8192;
 
//定义 KeepAlive 数据结构
Type
  TTCP_KEEPALIVE = packed record
    onoff: integer;
    keepalivetime: integer;
    keepaliveinterval: integer;
  end;
在idtcpserver的OnConnect事件里面加入以下代码:
var
  opt:Integer;
  klive, outKlive: TTCP_KEEPALIVE;
begin
  opt := 1;
    if setsockopt(AThread.Connection.Socket.Binding.Handle,SOL_SOCKET, SO_KEEPALIVE, @opt, SizeOf(opt)) <> 0 then
    begin
      Showmessage('setsockopt KeepAlive Error!');
    end;
    klive.onoff := 1;
    klive.keepalivetime := 3000;
    klive.keepaliveinterval := 1;
    if WSAIoctl(AThread.Connection.Socket.Binding.Handle, SIO_KEEPALIVE_VALS, @klive,
             SizeOf(TTCP_KEEPALIVE), @outKlive,
             SizeOf(TTCP_KEEPALIVE), @opt,0,nil) = SOCKET_ERROR then
    begin
      Showmessage('WSAIoctl KeepAlive Error!');
    end
end
在idtcpserver的OnException事件里面就能捕获到这个异常,并进行异常处理了
procedure Tfrmmain.IdTCPServer1Exception(AThread: TIdPeerThread;
  AException: Exception);
begin
  suiMemo1.Lines.Add('客户端'+inttostr(athread.handle)+'异常断开');
  if AThread.Connection.Connected then AThread.Connection.Disconnect;
end;
 
 
客户端的心跳处理(idtcpclient)
procedure Tfrmmain.IdTCPClient1Connected(Sender: TObject);
var
    opt:Integer;
  klive, outKlive: TTCP_KEEPALIVE;
begin
    opt := 1;
    if setsockopt(IdTCPClient1.Socket.Binding.Handle,SOL_SOCKET, SO_KEEPALIVE, @opt, SizeOf(opt)) <> 0 then
    begin
      Showmessage('setsockopt KeepAlive Error!');
    end;
    klive.onoff := 1;
    klive.keepalivetime := 3000;
    klive.keepaliveinterval := 1;
    if WSAIoctl(IdTCPClient1.Socket.Binding.Handle, SIO_KEEPALIVE_VALS, @klive,
             SizeOf(TTCP_KEEPALIVE), @outKlive,
             SizeOf(TTCP_KEEPALIVE), @opt,0,nil) = SOCKET_ERROR then
    begin
      Showmessage('WSAIoctl KeepAlive Error!');
    end;
end;
 
客户端的异常捕捉,我是放在客户端读取服务端发送过来数据的线程里面
procedure TReadThread.Execute;
var
  TestBuffer:TSendDataNet;
begin
  { Place thread code here }
  frmmain.log('Client Begin reading...');
  while permit do
  begin
    try
      frmmain.IdTCPClient1.ReadBuffer(TestBuffer,SizeOf(TestBuffer));
      sleep(100);
    except
      on e:Exception do
      begin
        permit:=False;
        if frmmain.IdTCPClient1.Connected then frmmain.IdTCPClient1.Disconnect;
        frmmain.RzStatusPane1.Caption:='断开;
        frmmain.LinkTimer.Enabled:=True;//这儿启动定时器重连服务端
      end;
    end;
  end;
  ThreadDestroy;
end;

转载于:https://www.cnblogs.com/moonwind/p/4434608.html

delphi idtcpclient和idtcpserver的心跳包相关推荐

  1. socket心跳机制图片_socket心跳包机制

    心跳包 心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包 心跳包的作用 网络中的接收和发送数据都是使用SOCKET进行实现.但 ...

  2. web socket 心跳包的实现方案

    web socket 心跳包的实现方案05/30/2010 现在网络环境错综复杂,socket心跳包是获得健康强壮的连接的有效解决方案,今天,我们就在web socket中实现心跳包方案,是的,尽管我 ...

  3. 【Java 网络编程】客户端 Socket 配置 ( 超时时间 | 端口复用 | Nagle 算法 | 心跳包机制 | 连接关闭机制 | 缓冲区大小 | 性能权重设置 | 紧急数据设置 )

    文章目录 I 设置读取超时时间 II Socket 复用绑定端口设置 III 开启 Nagle 算法 ( 沾包 ) IV 心跳包机制 V 连接关闭处理 VI Socket 紧急数据内敛设置 VII S ...

  4. Socket心跳包机制

    心跳包的发送,通常有两种技术 方法1:应用层自己实现的心跳包 由应用程序自己发送心跳包来检测连接是否正常,大致的方法是:服务器在一个 Timer事件中定时 向客户端发送一个短小精悍的数据包,然后启动一 ...

  5. webSocket使用心跳包实现断线重连

    首先new一个webscoket的连接 let noticeSocketLink = new WebSocket('webSocket的地址') 这里是连接成功之后的操作 linkNoticeWebs ...

  6. tcp连接探测Keepalive和心跳包

    采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃.当机.网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回.很多时候,这不是 ...

  7. 嵌入式开发之网络心跳包---阻塞和非阻塞以及是否有必要心跳包heartbeat

    1.1 TCP和UDP的心跳包是用来维持长连接的 心跳包只是用来检测socket的链接状态 2.1 非阻塞情况下TCP 心跳包是否有必要建立心跳包 需要, a.如果说 严格 检测掉线的话 那么不管是不 ...

  8. php websocket 心跳包,websocket 心跳包重连

    上次我们讲过了websocket断线重连的问题,那么久会有人提出疑问了,心跳包重连跟断线重连有什么区别呢? 其实这两个都是为了达到一个目的,那就是保证当前设备的网络状态保持通畅...而断线重连呢,只能 ...

  9. Socket连接心跳包的机制总结

    文章目录 Socket连接心跳包的机制总结 心跳包的由来 心跳包的作用 心跳包由服务端还是客户端发送? Socket连接心跳包的机制总结 心跳包的由来 心跳包之所以叫心跳包是因为:它像心跳一样每隔固定 ...

最新文章

  1. Java虚拟机详解----JVM常见问题总结
  2. Pointers On C 1
  3. 浅谈前端自动化构建 -- Grunt、Gulp、FIS
  4. TOP 1%的软件工程师和其他 99%有什么不同?
  5. C/C++里面的左移和右移
  6. 蚂蚁、字节、拼多多,你的简历能通过几家?
  7. C++容器(一)——vector
  8. 后台异常 - Content is not allowed in prolog
  9. 50个开源性能测试工具
  10. 8uftp怎么上传文件,8uftp怎么上传文件
  11. 2022最新第四方聚合支付系统源码+详细搭建教程
  12. 2020千月最新影视源码 对接苹果影视app小白零基础搭建视频教学可赚钱影视APP
  13. PHP语言之正则表达式
  14. python练习题(一):输入某年某月某日,判断这一天是这一年的第几天
  15. CRM系统怎么定价?
  16. 阿里视频云点播端体验Demo
  17. Linux网络设备驱动程序设计----刘文涛
  18. Nginx的安装使用----反向代理服务器
  19. 公众号运营,如何快速找到内容定位?
  20. 寒门再难出贵子?学会这个方法,跨越阶层不是梦

热门文章

  1. Blas SGEMM launch failed
  2. 使用MATLAB分析处理csv数据
  3. ajax响应码,jQuery 使用$ .ajax()处理HTTP响应代码
  4. java8循环_Java8里请不要再使用循环语句
  5. while循环(包含死循环、while嵌套)
  6. mysql实现知识图谱_基于电影知识图谱的智能问答系统学习记录
  7. python打砖块游戏算法设计分析_python小游戏--打砖块的实现与讲解(python自学总结系列)...
  8. jupyter notebook如何选择conda环境
  9. SAP License:FICO重要概念(二)-附常用技巧
  10. 简单设计企业级JOB平台