У меня есть приложение с клиентскими и серверными сокетами, использующее Indy, скомпилированное с Delphi 10.2.
Приложение имеет рабочий поток, который обрабатывает запросы из разных портов и записывает ответы в одном потоке, используя вызов чего-то вроде этого:
procedure TMyCommManager.WriteResponse(AHandler: TIdIOHandler; SomeData: SomeType);
var
idBytes: TidBytes;
PacketSize: Integer;
begin
SomeData.GetBytes(idBytes, PacketSize);
AHandler.Write(DataBuffer, PacketSize);
end;
Почти все время все работаеткак и ожидалось, но мы заметили, что рабочий поток время от времени зависает на производстве.После различных итераций мы наконец дошли до того, что все это происходит при вызове TidIOHandler.Write()
, и я совершенно уверен, что это происходит, потому что другой конец для одного порта не читает ответы из сокета.
После сброса на порт из другого конца рабочий поток размораживает и продолжает работать как положено.
Я нашел этот ответ от РемиЛебо на вопрос Delphi (Indy) Server Freezing при записи , где он упоминает в комментариях (выделено мое):
Indy использует блокирующие сокеты, поэтому если клиентне читает входящие данные на своем конце , в итоге внутренний буфер отправки сокета заполнится, и сокет будет заблокирован на стороне сервера, ожидая, пока клиент очистит буфер. Единственный способ избежать тупика в этом сценарии - это установить тайм-аут отправки на уровне сокета, используя API сокетов напрямую .Indy не реализует тайм-ауты отправки в своей логике.
Я ищу правильный способ установки этого тайм-аута через INDY или через прямой вызов API в Windows, но я застрял в этомпоэтому я прихожу сюда в поисках помощи.
Если это невозможно, я мог бы реализовать механизм Timeout во вторичном потоке, но я не уверен, как правильно сбросить соединение с этим вторичным потоком на моем конце, чтобы рабочий поток продолжил свою работу.