免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
delphi idtcpclient和idtcpserver的心跳包

最近有個(gè)項(xiàng)目需要用到socket通信,對(duì)于socket的網(wǎng)絡(luò)異常處理(程序異常退出或者網(wǎng)絡(luò)掉了)及重連糾結(jié)了好久,網(wǎng)上雖然有很多資料,但是都是從一個(gè)地方轉(zhuǎn)過(guò)來(lái)的,不夠詳細(xì),查了很久的資料才弄出來(lái)的,原來(lái)的出處給忘了。

環(huán)境:delphi7+indy控件(dephi7自帶)     工作需要才用delphi7,建議使用delphi2007及以上版本,delphi2007里面帶的indy控件版本是10.0,修復(fù)了很多以前的bug

使用心跳包的理由:(ps:以下理由是抄的,感覺意思和我當(dāng)初的初衷是一樣的)
有開發(fā)網(wǎng)絡(luò)應(yīng)用經(jīng)歷的人都知道,網(wǎng)絡(luò)中的接收和發(fā)送數(shù)據(jù)都是使用WINDOWS中的SOCKET進(jìn)行實(shí)現(xiàn)。但是如果此套接字已經(jīng)斷開,那發(fā)送數(shù)據(jù)和接收數(shù)據(jù)的時(shí)候就一定會(huì)有問題??墒侨绾闻袛噙@個(gè)套接字是否還可以使用呢?
  有人一定想到使用Send函數(shù)中的返回結(jié)果來(lái)進(jìn)行判斷。如果返回的長(zhǎng)度和自己發(fā)送出去的長(zhǎng)度一致,那就說(shuō)明這個(gè)套接字是可用的,否則此套接字一定出現(xiàn)了問題。但是我們并不是無(wú)時(shí)無(wú)刻的發(fā)送數(shù)據(jù)呀。如何解決呢?
  其實(shí)TCP中已經(jīng)為我們實(shí)現(xiàn)了一個(gè)叫做心跳的機(jī)制。如果你設(shè)置了心跳,那TCP就會(huì)在一定的時(shí)間(比如你設(shè)置的是3秒鐘)內(nèi)發(fā)送你設(shè)置的次數(shù)的心跳(比如說(shuō)2次),并且此信息不會(huì)影響你自己定義的協(xié)議。
 
原理網(wǎng)上都有,就是使用setsockopt函數(shù)和WSAIoctl函數(shù),網(wǎng)上光介紹了怎么使用心跳機(jī)制,沒有說(shuō)處理辦法。設(shè)置好心跳后,TCP就會(huì)在一定的時(shí)間(比如你設(shè)置的是3秒鐘)內(nèi)發(fā)送你設(shè)置的次數(shù)的心跳(比如說(shuō)2次),如果網(wǎng)絡(luò)異常(程序異常退出或者網(wǎng)絡(luò)掉了),心跳就會(huì)拋出一個(gè)錯(cuò)誤異常,我們只要知道在哪兒捕獲異常,就能知道網(wǎng)絡(luò)情況以及何時(shí)進(jìn)行重連了。
 
服務(wù)端的心跳處理(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 數(shù)據(jù)結(jié)構(gòu)
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事件里面就能捕獲到這個(gè)異常,并進(jìn)行異常處理了
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;
 
客戶端的異常捕捉,我是放在客戶端讀取服務(wù)端發(fā)送過(guò)來(lái)數(shù)據(jù)的線程里面
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;//這兒?jiǎn)?dòng)定時(shí)器重連服務(wù)端
      end;
    end;
  end;
  ThreadDestroy;
end;

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
delphi用IdTCPServer和IdTCPClient傳輸文件
DelPhi2007 中 使用Indy 的TCP連接教程
DELPHI網(wǎng)絡(luò)文件傳輸控制例程
讓IdTCPServer&IdTCPClient的應(yīng)用穿透NAT
delphi使用IdTCPServer、TIdTCPClient收發(fā)消息
TCP連接中網(wǎng)絡(luò)斷開后重新連接后的狀態(tài)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服