2012-02-07 30 views
4

我有一个Indy TCP连接的问题。我使用Turbo Delphi 2006和Indy 10. 我想从idTCPClient发送多个TCP包到idTCPServer。Indy TCPServer发送包太频繁时收不到TCPClient的所有包

它工作的很好,当我只想发送一个包,或者我在函数的两次调用之间插入一个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 

非常感谢您提前给出答案!

回答

4

每当您拨打Connect()时,都会创建一个新连接,并且TIdTCPServer将启动一个新线程来处理该连接(除非启用线程池)。这是你真正想要的吗?让客户端将连接打开一段时间并尽可能重复使用现有连接会更有效率。只有当你真的不再需要它时,例​​如当它闲置一段时间,才断开连接。建立一个新的连接是一个昂贵的操作,所以你应该尽可能地减少开销。

在客户端,当你调用Write(data),它会发送整个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; 
+0

谢谢您的回答!我将这些软件包合并为一个大包,我将它作为一个流读取,现在它可以工作。谢谢! – hunyadym 2012-02-09 22:23:44