DataSnap的如果网络断线,如何恢复?
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的如果网络断线,如何恢复?的更多相关文章
- 【12c】12c RMAN新特性之通过网络远程恢复数据库(RESTORE/Recover from Service)
[12c]12c RMAN新特性之通过网络远程恢复数据库(RESTORE/Recover from Service) 通过网络远程恢复数据库(Restore/Recover from Service) ...
- 在windows中安装OpenSSH,无密码登录,永远不断线
到这里下载最新安装包:https://github.com/PowerShell/Win32-OpenSSH/releases下载下来解压,然后用管理员打开服务器自带的PowerShell,运行下列命 ...
- RedisTemplate连接不释放、Redis断线不重连问题、Redis连接数高飙升
使用RedisTemplate操作Redis数据,但遇到网络断线后不会重新连接 毫无头绪 一顿捣鼓 最终解决 整理如下 帮助更多的人 1.起因 使用RedisTemplate 配置 开启了事务 ena ...
- iOS 网络框架编写总结
一,常用 1> 不错的处理接收到的网络图片数据的方法 id img= ISNSNULL(pic)?nil:[pic valueForKey:@"img"]; NSString ...
- MC3190终端配置冷启动自动恢复的方法
一. 网络配置的恢复 将当前文件夹下的注册表文件MC3190 Start Config.reg(见附件)复制到终端的Application文件夹内(可以通过数据线或ftp方式传送文件); 导出终端的网 ...
- mysql 恢复
一.备份的目的 做灾难恢复:对损坏的数据进行恢复和还原需求改变:因需求改变而需要把数据还原到改变以前测试:测试新功能是否可用 二.备份需要考虑的问题 可以容忍丢失多长时间的数据:恢复数据要在多长时间内 ...
- Oracle 12c Dataguard 数据库恢复
http://allthingsoracle.com/rolling-forward-a-physical-standby-database-using-the-recover-command/ 当主 ...
- mysql之6备份恢复
基本意义: 将数据另存到其他设备,以便于出现问题时恢复数据 为什么要备份: 灾难恢复:需求改变:测试 几个事先需要考虑的问题: 可以容忍丢失多长时间的数据?恢复要在多长时间内完成?是否 ...
- 【rabbitmq】RabbitMQ 集群与网络分区
网络分区(network partitions) 官网-网络分区 网络设备故障导致的网络分裂.比如,存在A\B\C\D\E五个节点,A\B处于同一子网,B\C\D处于另外一子网,中间通过交换机相连.若 ...
随机推荐
- 常州模拟赛d5t1 journalist
分析:出题人丧心病狂卡spfa......只能用dijkstar+堆优化. 主要的难点是字典序的处理上,一个想法是在做最短路的时候处理,边松弛边记录,比个大小记录最佳答案.具体的思路大概和最短路计数差 ...
- c++ primer note
---恢复内容开始--- 1.decltype 2.auto 3.cbegin 4.cend 5.constexpr 6.(*Parray)[10]=&arr; //Parray 指向一个含有 ...
- ngrinder的idea脚本开发环境配置
1.安装toriseSvn,安装一定要选择comandline (默认是没选择的) 2.下载groovy,解压缩,在开发工具(ps:idea,eclipse)中设置groovy安装路径 3.在网站处创 ...
- charts 画折线图
主题:指定日期内,不同地区的发布信息的数量的变化曲线 数据库是mongod 数据是58同城的发布的信息 整体思路: 1由于从数据库中拿到的数据,格式等方面并不一样能完全满足需求,需要对数据库中的数据进 ...
- 稻草人(bzoj 4237)
Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要 ...
- 高效的MySQL的批插入 BULK INSERT
原文:http://www.open-open.com/code/view/1453702496573 MySQL的批插入 BULK INSERT和load data的速度差不多,并且可靠. 语法如下 ...
- XP操作系统设置:[82]关机快捷键
磨镰刀不少割麦,掌握了快速关机的多种方法,在尴尬的时候说不定还真能派上用场呢. 工具/原料 手提电脑.台式电脑.Windows 操作系统. 方法一: 1 Windows XP 操作系统中有 ...
- 如何绕过Win8、Win10的systemsetting与注册表校验设置默认浏览器
*本文原创作者:浪子_三少,属Freebuf原创奖励计划,未经许可禁止转载 在win7时我们只需修改注册表就能设置默认浏览器,但是win8.win10下不能直接修改的因为同样的注册表项,win8.wi ...
- jquery 常用选择器 回顾 ajax() parent() parents() children() siblings() find() eq() has() filter() next()
1. $.ajax() ajax 本身是异步操作,当需要将 异步 改为 同步时: async: false 2.parent() 父级元素 和 parents() 祖先元素 的区别 parent ...
- 关于Java中强制类型转换的问题
为了更好的理解我们先看下面的例子: package com.yonyou.test; import java.util.ArrayList; import java.util.Iterator; im ...