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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM