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处于另外一子网,中间通过交换机相连.若 ...
随机推荐
- W3 School学习网站
http://www.w3school.com.cn/ 领先的 Web 技术教程 - 全部免费 在 w3school,你可以找到你所需要的所有的网站建设教程. 从基础的 HTML 到 CSS,乃至进阶 ...
- Redis的持久化——RDB
前面说到redis的三大特性:缓存.分布式内存数据库.持久化,所以今天将为大家介绍redis的两种数据持久化技术RDB和AOF, 先介绍RDB吧. 一.RDB是什么? 1.RDB全称redis dat ...
- ngrinder的idea脚本开发环境配置
1.安装toriseSvn,安装一定要选择comandline (默认是没选择的) 2.下载groovy,解压缩,在开发工具(ps:idea,eclipse)中设置groovy安装路径 3.在网站处创 ...
- tmux基本操作
安装和移除: // 安装 sudo apt-get install tmux // 移除 sudo apt-get remove tmux 常用命令: tmux [new -s 会话名 -n 窗口名] ...
- Java中String字符串toString()、String.valueOf()、String强转、+ ""的区别
Object#toString(): Object object = getObject(); System.out.println(object.toString()); 在这种使用方法中,因为ja ...
- Spring Boot集成Spring Data Reids和Spring Session实现Session共享
首先,需要先集成Redis的支持,参考:http://www.cnblogs.com/EasonJim/p/7805665.html Spring Boot集成Spring Data Redis+Sp ...
- 从实例看hibernate的主键生成策略
学习了hibernate会发现.hibernate中有实体类.实体类的映射文件.可是我们怎么样才干知道实体类的主键是如何的生成方式呢?hibernate提供的主键生成策略帮我们完美地解答了这个疑问.以 ...
- 第一个MapReduce程序——WordCount
通常我们在学习一门语言的时候,写的第一个程序就是Hello World.而在学习Hadoop时,我们要写的第一个程序就是词频统计WordCount程序. 一.MapReduce简介 1.1 MapRe ...
- GCD编程(封装GCD)
//GCDGroup 类 @interface GCDGroup : NSObject @property (strong, nonatomic, readonly) dispatch_group_t ...
- MySQL中insert ignore into, on duplicate key update,replace into,insert … select … where not exist的一些用法总结
在MySQL中进行条件插入数据时,可能会用到以下语句,现小结一下.我们先建一个简单的表来作为测试: CREATE TABLE `books` ( `id` ) NOT NULL AUTO_INCREM ...