1. 程式人生 > >Indy10中idTcpServer和idTcpClient的異常解決

Indy10中idTcpServer和idTcpClient的異常解決

今天重寫一個delphi7的CS架構的軟體,原本自帶的控制元件是Indy9。現在升級到Indy10,用delphi XE5開發。發現idTcpServer與idTcpClient的一些異常導致記憶體報錯。

1.idTcpServer端需要先啟動,idTcpClient再啟動去connect,TCP通道才算是建立。idTcpClient如果優先啟動,則建立不起來TCP通道。

解決方法:如果Cient先啟動,IdTCPC_DTU連線時判斷是否能連線上 如果不行就關閉。可以設定一個時鐘判斷是否連的上,等到idTcpServer連線時再啟動。

程式碼:

  try
    if not IdTCPC_DTU.Connected then
    begin
      IdTCPC_DTU.Connect;
      Timer_CSSend.Enabled := True;
    end;
  Except
    on e:Exception do
    begin
      //CS關閉
      if IdTCPC_DTU.Connected then
        IdTCPC_DTU.IOHandler.Close;
      IdTCPC_DTU.Disconnect;
    end;
  end; 

2.如果idTcpServer端在連線過程中強制關閉S端會報錯(我一開始看網上帖子會是快取資料沒清空,但我跟進去反而發現執行緒出現釋放不完整。反正出錯方面很多很複雜,基本都遮蔽,有些甚至是無法遮蔽的直接記憶體報錯),如果idTcpClient在連線過程中強制關閉則不會報錯。如果idTcpServer端在idTcpClient強制關閉後才關閉是不會報錯的。

解決方法:idTcpServer端在被強制關閉S端前傳送使idTcpClient端關閉的斷開控制命令(這裡的斷開控制命令,idTcpClient端接收到後會自我先斷開),先讓idTcpClient端關閉,在idTcpServer端進行關閉。

程式碼:

function Tfrm_Main.TCPServerWrite(Client: TThreadList; WriteStr: String): Boolean;
var
  RecThread: TIdContext;
  RecClient: PClient;
  i: Integer;
begin
  Result := false;
  with Client.LockList do
  try
    for i := 0 to Count-1 do
    begin
      RecClient := Items[i];
      RecThread := RecClient.Thread;
      RecThread.Connection.Socket.Write(WriteStr);
      Result := true;
    end;
  except
  end;
  Client.UnlockList;
end;

procedure Tfrm_Main.FormClose(Sender: TObject; var Action: TCloseAction);
var
  i: Integer;
begin
  WriteStr := 'close;'+ #10;//假設傳送close,在idTcpClient端解析為關閉埠
  TCPServerWrite(m_Clients,WriteStr);
  try
    if IdTCPServer.Active then
      IdTCPServer.Active := false;
  except
  end;
    m_Clients.Free;
    m_Clients := nil;
end;

我覺得應該還有更好的解決方法,當然如果大家有更好的經驗與方法,或者是對idTcpServer和idTcpClient研究比較透的,歡迎留言郵件交流。