-
Существует тред, в котором с помощью инди читаются данные из сокета. Читаются с тайм-аутом, идет вызов IdWinsock2.select. Можно ли как-то прервать вызов IdWinsock2.select, не разрушая тред? Тайм-аут на чтение нужен порядка 10 минут, не представляется возможным дожидаться, пока он сработает и тред закончит работу по тайм-ауту. Прерывание нужно для корректного закрытия приложения. Тред или треды могут долго 'висеть' в IdWinsock2.select, вот - хочется этот вызов как-то приостановить.
-
Получается какая бяка. Клиенты открывают соединения, общаются с нашим сервером и соединение оставляют открытым (хотя положено его закрывать). Клиенты могут быть сторонними, сервер - наш. Сервер, пообщавшись с клиентами, пытается вытянуть из сокета очередную 'команду' и остается 'висеть' на 10 минут, клиент больше ему ничего не шлет. Вот хочется - тред сервера, в котором идет общение с клиентом прибить раньше, чем сработает тайм-аут.
-
> Вот хочется - тред сервера, в котором идет общение с клиентом > прибить раньше, чем сработает тайм-аут.
зачем такой большой таймаут?
> Можно ли как-то прервать вызов IdWinsock2.select, не разрушая > тред?
когда то читал, что вроде бы сокет закрыть достаточно, но я не уверен, что это безопасно.
-
> что вроде бы сокет закрыть достаточно, но я не уверен, что это безопасно.
- вполне безопасно(ресурсы выделенные под сокет после этого еще минуты две живут(TIME_WAIT state))... - честный WSAECONNABORTED(вроде) будет... (во всяком случае для overlapped - WSA_OPERATION_ABORTED приходит)
> и соединение оставляют открытым (хотя положено его закрывать).
- угу, а отслеживание ошибок(в том числе и WSAECONNRESET) в твоем select делается? (exceptfds - An optional pointer to a set of sockets to be checked for errors.)
З.Ы. И SO_KEEPALIVE - полезная вещь, т.к. если с "другой стороны" коммутатора выдернуть шнур - "там" сокет сбросится, а "тут" - если только слушать - то будет ждать до морковкиного заговения(нету там таймаута на возобновление передачи(если все ACK уже пришли) - хоть через год)...
-
> Тайм-аут ..нужен порядка 10 минут
Ужас какой ..
одной-двух мс достаточно
-
> одной-двух мс достаточно
Клиент может связываться через не быстрое и нестабильное соединение (GPRS и иже). 10 минут - то, наверно, действительно много, но 1-2 мс - совсем мало, а обрыв раньше времени крайне нежелателен.
-
> но 1-2 мс - совсем мало
С чего бы вдруг ?
цикл подождать пару мс если доступны некие данные то начало получить их обработать отправить если нужно ответ конец конец цикла
-
Сделал так (немного модифицированный метод ReadBytes):
procedure TIdIOHandler.ReadBytesTimeOut(var VBuffer: TIdBytes; AByteCount: integer;
AAppend: boolean = True; CheckForTerminate: TBoolFunc = nil);
begin
Assert(FInputBuffer <> nil);
while FInputBuffer.Size < AByteCount do
begin
try
if ReadFromSource(False, ReadTimeout) > 0 then
if FInputBuffer.Size >= AByteCount then
Break; except
on E: EIdReadTimeout do
begin
if Assigned(CheckForTerminate) and CheckForTerminate then
begin
ZeroMemory(VBuffer, AByteCount);
Exit;
end;
Sleep(1000);
end;
on E: Exception do
Exit;
end;
CheckForDisconnect(True, True);
end;
FInputBuffer.ExtractToBytes(VBuffer, AByteCount, AAppend);
end;
тайм-аут сделал 1 секунду. Еще пока не тестировали особенно, но, похоже, что нормально работает.
-
> Дмитрий Белькевич (21.11.12 13:59) [7]
> Sleep(1000);
А зачем он нужен? Что дает?
-
> А зачем он нужен? Что дает?
Вообще - то не сильно он там нужен. Он был нужен, когда задержка была 2 мс. У нас стоит эврикалог, которая обрабатывает каждое исключение. Причем обрабатывает достаточно долго (правда, там есть довольно большой оверхид по работе, как я понял, можно лишнего всякого поотключать на конкретный тред - будет легче). То с 2 мс софт занимался почти только тем, что обрабатывал свои же исключения. Задержка помогла. Так же помогло увеличение до секунды тайм-аута. Но - если тредов будет много, а так бывает, то софт опять будет заниматься только обработкой исключений. Но я с настройкой эврики поиграюсь, думаю, можно сделать обработку быстрее.
-
работай асинхронно
|