Конференция "Сети" » Можно ли как-то прервать IdWinsock2.select?
 
  • Дмитрий Белькевич (17.11.12 20:06) [0]
    Существует тред, в котором с помощью инди читаются данные из сокета. Читаются с тайм-аутом, идет вызов IdWinsock2.select. Можно ли как-то прервать вызов IdWinsock2.select, не разрушая тред? Тайм-аут на чтение нужен порядка 10 минут, не представляется возможным дожидаться, пока он сработает и тред закончит работу по тайм-ауту. Прерывание нужно для корректного закрытия приложения. Тред или треды могут долго 'висеть' в IdWinsock2.select, вот - хочется этот вызов как-то приостановить.
  • Дмитрий Белькевич (17.11.12 20:11) [1]
    Получается какая бяка. Клиенты открывают соединения, общаются с нашим сервером и соединение оставляют открытым (хотя положено его закрывать). Клиенты могут быть сторонними, сервер - наш. Сервер, пообщавшись с клиентами, пытается вытянуть из сокета очередную 'команду' и остается 'висеть' на 10 минут, клиент больше ему ничего не шлет. Вот хочется - тред сервера, в котором идет общение с клиентом прибить раньше, чем сработает тайм-аут.
  • DVM © (18.11.12 16:15) [2]

    > Вот хочется - тред сервера, в котором идет общение с клиентом
    > прибить раньше, чем сработает тайм-аут.

    зачем такой большой таймаут?


    > Можно ли как-то прервать вызов IdWinsock2.select, не разрушая
    > тред?

    когда то читал, что вроде бы сокет закрыть достаточно, но я не уверен, что это  безопасно.
  • han_malign (19.11.12 18:20) [3]

    > что вроде бы сокет закрыть достаточно, но я не уверен, что это  безопасно.

    - вполне безопасно(ресурсы выделенные под сокет после этого еще минуты две живут(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 уже пришли) - хоть через год)...
  • Сергей М. © (19.11.12 22:10) [4]

    > Тайм-аут ..нужен порядка 10 минут


    Ужас какой ..

    одной-двух мс достаточно
  • Дмитрий Белькевич (20.11.12 01:37) [5]

    > одной-двух мс достаточно


    Клиент может связываться через не быстрое и нестабильное соединение (GPRS и иже). 10 минут - то, наверно, действительно много, но 1-2 мс - совсем мало, а обрыв раньше времени крайне нежелателен.
  • Сергей М. © (20.11.12 10:37) [6]

    > но 1-2 мс - совсем мало


    С чего бы вдруг ?

    цикл
     подождать пару мс
     если доступны некие данные то
       начало
         получить их
         обработать
         отправить если нужно ответ
       конец  
    конец цикла
  • Дмитрий Белькевич (21.11.12 13:59) [7]
    Сделал так (немного модифицированный метод ReadBytes):


    procedure TIdIOHandler.ReadBytesTimeOut(var VBuffer: TIdBytes; AByteCount: integer;
     AAppend: boolean = True; CheckForTerminate: TBoolFunc = nil);
    begin
     Assert(FInputBuffer <> nil);
     // Read from stack until we have enough data
     while FInputBuffer.Size < AByteCount do
     begin
       try
         if ReadFromSource(False, ReadTimeout) > 0 then
           if FInputBuffer.Size >= AByteCount then
             Break;// we have enough data now
       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 15:05) [8]

    > Дмитрий Белькевич   (21.11.12 13:59) [7]



    > Sleep(1000);

    А зачем он нужен? Что дает?
  • Дмитрий Белькевич (23.11.12 04:54) [9]

    > А зачем он нужен? Что дает?


    Вообще - то не сильно он там нужен. Он был нужен, когда задержка была 2 мс. У нас стоит эврикалог, которая обрабатывает каждое исключение. Причем обрабатывает достаточно долго (правда, там есть довольно большой оверхид по работе, как я понял, можно лишнего всякого поотключать на конкретный тред - будет легче). То с 2 мс софт занимался почти только тем, что обрабатывал свои же исключения. Задержка помогла. Так же помогло увеличение до секунды тайм-аута. Но - если тредов будет много, а так бывает, то софт опять будет заниматься только обработкой исключений. Но я с настройкой эврики поиграюсь, думаю, можно сделать обработку быстрее.
  • Polevi © (04.12.12 21:42) [10]
    работай асинхронно
 
Конференция "Сети" » Можно ли как-то прервать IdWinsock2.select?
Есть новые Нет новых   [134427   +34][b:0][p:0.001]