timer代码很简单:
var adbsevertime :TDateTime;
begin
try
adbsevertime :=
ClientModule1.ServerMethods1Client.GetDbServerTime;
if adbsevertime <> 0 then
begin
gdbStatus := true;
TimerReconnet.Enable:=false;
end;

except
on E: Exception do
begin

TimerReconnet.Enable:=true;
end;
end;
end;

GetDbServerTime是dephi自动生成的客户端访问中间层的方法

网上找到三种方法:
http://www.cnblogs.com/yagzh2000/archive/2013/04/27/3046637.html

http://blog.csdn.net/sunstone/article/details/5023718
http://blog.163.com/bin0315@126/blog/static/4066264220128414025829/
类似)

http://bbs.2ccc.com/topic.asp?topicid=396438

我每个测试一下,到时候结果通知大家。

我来说下这一天的成果:
因为自己很少用datasnap,然后网上对indy有偏见言辞,我抱着这个心态开始实验:

因为我用的是 datasnap rest 服务,也就是没有用tcp,用的是http,网上的资料对我来说初看没有用。xe2对于tcpconnection设置了心跳包属性,也对我来说无用。
因为用的是http,用后即关闭,所以心跳包是否有用,我也不清楚。
怎么办呢?最后我找到TIdHTTPWebBrokerBridge这个实例Fserver里面有个onconnect事件,可以用,于是就手写了事件照猫画虎把delphi2010的代码粘贴下来了,不知道是否用。
代码如下:
 FServer := TIdHTTPWebBrokerBridge.Create(Self);
  FServer.OnConnect:=ServerConnect;
  FServer.OnDisconnect:=  ServerDisConnect ;

实现代码:
procedure TForm1.ServerConnect(AContext: TIdContext);
var
  Val: TCP_KeepAlive;
  Ret: DWORD;
  conne: tidtcpconnection;
  aip, aport, ausername, apass: string;
begin
 //验证
  conne := TIdTCPConnection(AContext.Connection);
  if conne <> nil then
  begin
    aip := conne.Socket.Binding.PeerIP;
    aport := inttostr(conne.Socket.Binding.PeerPort);
//  ausername := DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName];
//  apass := DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password];
//  if (ausername <> 'jiangbin') and (apass <> '2010') then
//    DSConnectEventObject.DbxConnection.Destroy
//  else
//    fr_main.memo1.Lines.add(aip + ':' + aport + '  名称:' + ausername);

//心跳包代码
    Val.OnOff := 1;
    Val.KeepAliveTime := 5000;
    Val.KeepAliveInterval := 3000;
    WSAIoctl(conne.Socket.Binding.Handle, IOC_IN or IOC_VENDOR or 4, @Val,
      SizeOf(Val), nil, 0, @Ret, nil, nil);
  end;

end;

procedure TForm1.ServerDisConnect(AContext: TIdContext);
var
  conne: tidtcpconnection;
  aip, aport, ausername, apass: string;
  i: integer;
begin
//断开后清除连接IP及端口

conne := TIdTCPConnection(AContext.Connection);
  if conne <> nil then
  begin
    aip := conne.Socket.Binding.PeerIP;
    aport := IntToStr(conne.Socket.Binding.PeerPort);
  end;

end;

但是不知道是否有用,待测。

另外,我在调试过程中,发现indy并不是想象的那么差,很完善
其实delphi事实是调用tidhttp 完成rest服务的,只是我这边有个问题,就是如果断线,调用异常,再次调用服务,就会出现服务器的index of bounds越界错误,(主要是构建http头,出现异常),这个应该是一个Indy bug吧,所以我准备临界来处理datasnap的中间层请求,保证异常后,不能同时再被访问,这样就可以了。

解决如果出现HTTP/1.1 403 Session has expired,datasnap不能重连功能,刚开始如果客户端正常连接中间层,然后中间层杀掉 ,客户端由于是用老的session去连接中间层,会被重新启动的中间层认为session过期。所以一直是返回raise,无限期不能重连。
解决方案,出现session错误时,把sessionid清空。

我发现问题跟tidhttp一毛钱关系没有,说明indy代码还是很不错的啊:)只是datasnap的代码未考虑异常。

解决如下:找到delphi源代码DSClientRest文件,复制到你的项目文件夹中,找到

procedure ExecuteCommand(ACommand: TDSRestCommand; const ARequestFilter, AAccept: string); overload;

把原先的1129行
ExecuteRequest(ACommand.Connection.HTTP, LURL, ACommand.RequestType, ACommand.Connection.LoginProperties.UserName, ACommand.Connection.LoginProperties.Password, ACommand.Parameters, ARequestFilter, AAccept,
    LSessionID,
    procedure
    begin
      ACommand.Connection.SessionExpired;
    end,
    procedure(ASessionID: string)
    begin
      if ASessionID <> '' then
        ACommand.Connection.SessionID := ASessionID;
    end);

改为:

try
  ExecuteRequest(ACommand.Connection.HTTP, LURL, ACommand.RequestType, ACommand.Connection.LoginProperties.UserName, ACommand.Connection.LoginProperties.Password, ACommand.Parameters, ARequestFilter, AAccept,
    LSessionID,
    procedure
    begin
      ACommand.Connection.SessionExpired;
    end,
    procedure(ASessionID: string)
    begin
      if ASessionID <> '' then
        ACommand.Connection.SessionID := ASessionID;
    end);
  except

on E:Exception do
   begin
     if Pos('Session has expired',E.Message)>0 then
     begin
      ACommand.Connection.SessionID:='';
     end;
     raise;
   end;

end;

既可,这样,重连中间层可以实现了。

经过二个多月对于datasnap的一个项目学习,发现emb的人喜欢把程序员当做刚做程序的小白,所以代码很完善,让你很简单就建立了一个rest 服务(内部细节都由emb帮助你做好了)。但是他们处于实验室阶段,有时候没有考虑真实环境的差异,特别是一些异常未做处理。也就是说 有些坑需要你自己去填,但是填完后,发现datasnap还是不错的。:-)

http://bbs.2ccc.com/topic.asp?topicid=524327

DataSnap的如果网络断线,如何恢复?的更多相关文章

  1. 【12c】12c RMAN新特性之通过网络远程恢复数据库(RESTORE/Recover from Service)

    [12c]12c RMAN新特性之通过网络远程恢复数据库(RESTORE/Recover from Service) 通过网络远程恢复数据库(Restore/Recover from Service) ...

  2. 在windows中安装OpenSSH,无密码登录,永远不断线

    到这里下载最新安装包:https://github.com/PowerShell/Win32-OpenSSH/releases下载下来解压,然后用管理员打开服务器自带的PowerShell,运行下列命 ...

  3. RedisTemplate连接不释放、Redis断线不重连问题、Redis连接数高飙升

    使用RedisTemplate操作Redis数据,但遇到网络断线后不会重新连接 毫无头绪 一顿捣鼓 最终解决 整理如下 帮助更多的人 1.起因 使用RedisTemplate 配置 开启了事务 ena ...

  4. iOS 网络框架编写总结

    一,常用 1> 不错的处理接收到的网络图片数据的方法 id img= ISNSNULL(pic)?nil:[pic valueForKey:@"img"]; NSString ...

  5. MC3190终端配置冷启动自动恢复的方法

    一. 网络配置的恢复 将当前文件夹下的注册表文件MC3190 Start Config.reg(见附件)复制到终端的Application文件夹内(可以通过数据线或ftp方式传送文件); 导出终端的网 ...

  6. mysql 恢复

    一.备份的目的 做灾难恢复:对损坏的数据进行恢复和还原需求改变:因需求改变而需要把数据还原到改变以前测试:测试新功能是否可用 二.备份需要考虑的问题 可以容忍丢失多长时间的数据:恢复数据要在多长时间内 ...

  7. Oracle 12c Dataguard 数据库恢复

    http://allthingsoracle.com/rolling-forward-a-physical-standby-database-using-the-recover-command/ 当主 ...

  8. mysql之6备份恢复

    基本意义: 将数据另存到其他设备,以便于出现问题时恢复数据     为什么要备份: 灾难恢复:需求改变:测试     几个事先需要考虑的问题: 可以容忍丢失多长时间的数据?恢复要在多长时间内完成?是否 ...

  9. 【rabbitmq】RabbitMQ 集群与网络分区

    网络分区(network partitions) 官网-网络分区 网络设备故障导致的网络分裂.比如,存在A\B\C\D\E五个节点,A\B处于同一子网,B\C\D处于另外一子网,中间通过交换机相连.若 ...

随机推荐

  1. 【2018.10.20】noip模拟赛Day3 飞行时间

    今天模拟赛题目 纯考输入的傻逼题,用$scanf$用到思想僵化的我最终成功被$if$大法爆$0$了(这题只有一组$100$分数据). 输入后面那个$(+1/2)$很难$if$判断,所以我们要判两个字符 ...

  2. leetcode 349 map

    只需要用map来标记1,今儿通过map的值来得到重叠的部分 class Solution { public: vector<int> intersection(vector<int& ...

  3. bzoj2748 [HAOI2012]音量调节 背包

    Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改 ...

  4. ubuntu问题解答集锦

    一.su root提示认证失败 su root提示认证失败 ubuntu root是默认禁用了,不答应用root登陆,所以先要设置root密码.   执行:sudo passwd root 接着输入密 ...

  5. KVM 存储虚拟化

    KVM 的存储虚拟化是通过存储池(Storage Pool)和卷(Volume)来管理的. Storage Pool 是宿主机上可以看到的一片存储空间,可以是多种类型,后面会详细讨论.Volume 是 ...

  6. Codevs 1021 玛丽卡==洛谷 P1186

    时间限制: 2 s 空间限制: 128000 KB  题目等级 : 大师 Master  题目描述 Description 麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复. 因为她和他们不住在同一个 ...

  7. 【Codeforces Round #502 (Div. 1 + Div. 2) 】

    A:https://www.cnblogs.com/myx12345/p/9843032.html B:https://www.cnblogs.com/myx12345/p/9843050.html ...

  8. BZOJ4726: [POI2017]Sabota?

    $n \leq 500000$的树,开始有一个点是坏的,如果一个子树中坏点比例(不包括根节点)超过x那这整棵子树就会变坏,问最坏情况下不超过$K$个坏点的情况下$x$最小是多少. 被坑成傻逼.. 可以 ...

  9. hihocoder #1290 : Demo Day

    传送门 #1290 : Demo Day 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 You work as an intern at a robotics star ...

  10. NOJ 1111 保险箱的密码 【大红】 [区间dp]

    传送门 保险箱的密码 [大红] 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 118            测 ...