Indy TCPServer не получает все пакеты от TCPClient при слишком частой отправке пакетов



У меня проблема с подключением Indy TCP. Я использую Turbo Delphi 2006 с Indy 10.
Я хочу отправить несколько пакетов TCP с данным idTCPClient idTCPServer.



Это прекрасно работает, когда я хочу отправить только один пакет, или я вставляю команду sleep(100) между двумя вызовами функции. Но если я вызываю эту функцию слишком часто, она не вызывает onExecute сервера каждый раз.



Мой код для отправки:



procedure SendData(var data: TIdBytes) ;
begin
FormMain.IdTCPClient.Connect ;
FormMain.IdTCPClient.Socket.Write(data);
FormMain.IdTCPClient.Disconnect ;
end ;


Я вызываю эту функцию несколько раз (5-10 раз в a во-вторых), и хочу обработать все эти пакеты в моем серверном приложении:



procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
data: TIdBytes ;
begin
AContext.Connection.IOHandler.ReadBytes(data, 4, false)
// processing data
end


Заранее благодарю вас за ответы!

690   1  

1 ответ:

Каждый раз, когда вы вызываете 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;

Comments

    Ничего не найдено.