我有Indy TCP连接的问题.我使用Turbo Delphi 2006和Indy 10. 我想从idTCPClient发送多个TCP包到idTCPServer. 当我只想发送一个包,或者在函数的两次调用之间插入sleep(100)命令时,它工作正常.但是,如果我
我想从idTCPClient发送多个TCP包到idTCPServer.
当我只想发送一个包,或者在函数的两次调用之间插入sleep(100)命令时,它工作正常.但是,如果我过于频繁地调用此函数,则每次都不会调用服务器的onExecute.
我的发送代码:
procedure SendData(var data: TIdBytes) ; begin FormMain.IdTCPClient.Connect ; FormMain.IdTCPClient.Socket.Write(data); FormMain.IdTCPClient.Disconnect ; end ;
我多次调用此函数(每秒5-10次),并希望在我的服务器应用程序中处理所有这些包:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); var data: TIdBytes ; begin AContext.Connection.IOHandler.ReadBytes(data, 4, false) // processing data end
提前感谢您的回答!
每次调用Connect()时,您都在创建一个新连接,TIdTCPServer将启动一个新线程来处理该连接(除非您启用线程池,即).那是你真正想要的吗?让客户端在一段时间内保持连接打开并尽可能多地重用现有连接会更有效.只有当你真的不再需要连接时才会断开连接,例如当它闲置一段时间时.建立新连接在两端都是一项昂贵的操作,因此您应尽可能减少开销.在客户端,当您调用Write(数据)时,它将发送整个TIdBytes,但您不会将该TIdBytes的长度发送到服务器,因此它知道预期的字节数. TIdIOHandler.Write(TIdBytes)不会为您执行此操作,您必须手动执行此操作.
在服务器端,您告诉ReadBytes()一次只读取4个字节.在每个4字节的块之后,您将退出OnExecute事件处理程序并等待再次调用它以读取下一个4字节的块.除非客户端源TIdBytes的长度是4的偶数倍,否则ReadBytes()会在尝试读取客户端的最后一个小于4个字节的块时引发异常(导致服务器断开连接),因此服务器代码不会收到该块.
试试这个:
procedure SendData(var data: TIdBytes) ; begin FormMain.IdTCPClient.Connect; try FormMain.IdTCPClient.IOHandler.Write(Longint(Length(data))); FormMain.IdTCPClient.IOHandler.Write(data); finally FormMain.IdTCPClient.Disconnect; end; end; procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); var data: TIdBytes; begin with AContext.Connection.IOHandler do ReadBytes(data, ReadLongint, false); // process data end;
话虽如此,如果因任何原因更改客户端代码以发送TIdBytes长度不是一个选项,那么请使用此服务器代码:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); var LBytes: Integer; data: TIdBytes; begin // read until disconnected. returns -1 on timeout, 0 on disconnect repeat until AContext.Connection.IOHandler.ReadFromSource(False, 250, False) = 0; AContext.Connection.IOHandler.InputBuffer.ExtractToBytes(data); // process data end;
要么:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); var strm: TMemoryStream; data: TIdBytes; begin strm := TMemoryStream.Create; try // read until disconnected AContext.Connection.IOHandler.ReadStream(strm, -1, True); strm.Position := 0; ReadTIdBytesFromStream(strm, data, strm.Size); finally strm.Free; end; // process data end;
要么:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); var strm: TMemoryStream; begin strm := TMemoryStream.Create; try // read until disconnected AContext.Connection.IOHandler.ReadStream(strm, -1, True); // process strm.Memory up to strm.Size bytes finally strm.Free; end; end;