Indy10中idTcpServer和idTcpClient的異常解決
阿新 • • 發佈:2019-02-08
今天重寫一個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研究比較透的,歡迎留言郵件交流。