Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2007.03.04;
Скачать: [xml.tar.bz2];

Вниз

CloseSocket() в неблокирующем режиме. Вопрос.   Найти похожие ветки 

 
DVM ©   (2006-09-26 11:25) [0]

Сокет находится в неблокирующем режиме. Я закрываю сокет функцией CloseSocket(). Вопрос - как мне с гарантией удостовериться, что сокет закрылся. Следом за сокетом мне надо уничтожить поток, в котором сокет используется, но я опасаюсь как бы поток не завершился раньше того как система выполнит всю работу по закрытию сокета. Иначе AV.


 
Сергей М. ©   (2006-09-26 11:35) [1]


> Иначе AV


Приведи код, в котором ты получаешь AV после CloseSocket()..


 
DVM ©   (2006-09-26 11:47) [2]


> Приведи код, в котором ты получаешь AV после CloseSocket().
> .

Он очень большой, но постараюсь описать подробнее.

Поток делает коннект примерно следующим образом:

function THTTPThread.SocketConnect: integer;
var
 Len, Res: integer;
 Block: Cardinal;
 rfd, wfd: TFDSet;
 FTimeout2: TTimeVal;
begin
 Result := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 if Result <> INVALID_SOCKET then
   begin
     Block := 1;
     ioctlsocket(Result, FIONBIO, Block);
     Len := SizeOf(FAddr);
     Res := Connect(Result, @FAddr, Len);
     FD_ZERO(rfd);
     FD_ZERO(wfd);
     FTimeout2.tv_sec := 2;
     FTimeout2.tv_usec := 0;
     while not terminated do
       begin
         FD_SET(result, rfd);
         FD_SET(result, wfd);
         case select(0, @rfd, @wfd, nil, @FTimeOut2) of
           -1: begin
                 CloseSocket(Result);
                 Result := -1;
               end;
            0: sleep(5);
         else
           begin
             Block := 0;
             ioctlsocket(Result, FIONBIO, Block);
             break;
           end;  
         end;
       end;
   end
 else
   begin
     CloseSocket(Result);
     Result := -1;
   end;
end;

Сначала сокет находится в неблокирующем режиме, потом я его перевожу в блокирующий. Это сделано для того, чтобы ускорить закрытие потока ожидающего connect().

В основном потоке программы я закрываю соединение и вторичный поток так:

 if FThread <> nil then
   begin
     CloseSocket(FThread.Sock);
     FThread.Terminate;
     FThread.WaitFor;
     FThread.Free;
     FThread := nil;
   end;

Вот я и подумал, а вдруг на момент закрытия сокета он находится в неблокирующем режиме и CloseSocket вернет управление сразу. А далее поток умрет быстрее чем система сокет закроет.

Подмечено, что AV возникает при включенном антивирусе касперского 6 чаще всего. Без него очень очень редко.


 
DVM ©   (2006-09-26 11:51) [3]

Если изменить так:

if FThread <> nil then
  begin
    ///// CloseSocket(FThread.Sock);
    FThread.Terminate;
    FThread.WaitFor;
    FThread.Free;
    FThread := nil;
  end;

То вроде работает нормально. (Сижу тестирую). Но поток закрывается теперь медленнее 2-3 секунды. Раньше почти мгновеннно.


 
DVM ©   (2006-09-26 11:56) [4]

Так же, наверное, замечу, что обращение к FThread.Sock в объекте потока сделано так:

function THTTPThread.GetSock: integer;
begin
 FCriticalSection.Enter;
 try
   Result := FSock;
 finally
   FCriticalSection.Leave;
 end;
end;


 
Сергей М. ©   (2006-09-26 12:03) [5]

Приведенное тело метода SocketConnect не может вызвать AV - исключение возникает где-то за его пределами. Точнее - на строчке кода, адрес XXXXXXXX которого фигурирует в сообщении об исключении "Access violation at address XXXXXXXX ...".

Ну и явная несуразность здесь присутствует:

if Result <> INVALID_SOCKET then
... //гнездо успешно создано
else
  //гнездо не создано
  begin
    CloseSocket(Result); //закрывать-то при этом нечего - гнездо же не создано !
    Result := -1;
  end;
end;


 
DVM ©   (2006-09-26 12:07) [6]


> Приведенное тело метода SocketConnect не может вызвать AV
> - исключение возникает где-то за его пределами. Точнее -
>  на строчке кода, адрес XXXXXXXX которого фигурирует в сообщении
> об исключении "Access violation at address XXXXXXXX ...".
>

Дело в том, что на моей машине повторить ошибку не получается. Она возникает у некоторых пользователей и весьма редко. Строку выявить пока не получается.

> Ну и явная несуразность здесь присутствует:

Да, действительно, не заметил.


 
Сергей М. ©   (2006-09-26 12:09) [7]


> поток закрывается теперь медленнее 2-3 секунды


Вместо connect+select используй WSAAsyncSelect/WSAEventSelect + WSAConnect, тогда твой поток сможет оперативно реагировать и на событие коннекта и на сигналы синхронизации, посылаемые потоку в качестве команды "закругляться немедленно"


 
Сергей М. ©   (2006-09-26 12:09) [8]


> Строку выявить пока не получается


Почему ?


 
DVM ©   (2006-09-26 12:18) [9]


> Почему ?

Чтобы выявить строку, надо дождаться появления ошибки. Ошибка явление крайне редкое и на моем компьютере, как я уже писал, почему то не появляется вовсе. Это главная проблема.

Насчет асинхронных Windows сокетов я подумаю, но, честно говоря, хочется обойтись обычными.


 
Сергей М. ©   (2006-09-26 12:28) [10]


> хочется обойтись обычными


Тогда таймаут делай насколько возможно малым.
Это позволит потоку оперативно реагировать на флаг Terminated


> надо дождаться появления ошибки


Не стоит ждать ее сложа руки. К этому моменту ты д.б. вооружен.
Юзер - существо как правило ненадежное, ленивое и недисциплинированное). Маловероятно что юзер ломанется со всех ног докладывать тебе дословный текст исключения тут же после его возникновения (если он вообще почешется по этому поводу), поэтому есть резон обрабатывать глобально все необработанные локально исключения, формировать и посылать протокол таких исключений себе любимому, например, мылом.


 
DVM ©   (2006-09-26 15:33) [11]

Попутно обнаружил крайне странную вещь! Оказывается KAV 6.0 при включенном анализе HTTP трафика портит данные на выходе. Т.е. они отличаются от того, что на входе.

Если в ответе HTTP сервера приходящем ко мне должно быть изначально #13#10#13#10 - конец заголовка ответа сервера, то после прохождения через касперского получается #13#10#13#10#10#10.

Нет слов!


 
Сергей М. ©   (2006-09-26 16:10) [12]


> DVM ©   (26.09.06 15:33) [11]


При чем здесь антивирь Кашмарского ?)
Ты со своей логикой разберись) ...


 
DVM ©   (2006-09-26 17:52) [13]


> При чем здесь антивирь Кашмарского ?)
> Ты со своей логикой разберись) ...

Я же написал "попутно". Со своей логикой разбираюсь. Кроме того, некоторые проблемы с работой моей логики по всей видимости все-таки связаны с данным антивирусом. Проблемы причем не только у меня. Проблемы у многих программ, принимающих потоковые данные типа видео, звука и т.д. В справке для KAV 6 так и написано.


 
DVM ©   (2006-09-26 17:53) [14]

И то что я написал в [11] - это же явный баг.


 
Сергей М. ©   (2006-09-26 21:04) [15]


> В справке для KAV 6 так и написано


"Упалпацтул"(С) славарь падонкафф



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2007.03.04;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.041 c
15-1170678001
novill
2007-02-05 15:20
2007.03.04
Простая задача по математике, не могу решить :(


15-1170699994
Nic
2007-02-05 21:26
2007.03.04
Вызов dll-функции из C# возможен или нет?


9-1145028173
grisme
2006-04-14 19:22
2007.03.04
Небо на OpenGL


1-1168630485
Dmitry_177
2007-01-12 22:34
2007.03.04
Определить путь к программе зная ее хендл окна


2-1171134658
niil
2007-02-10 22:10
2007.03.04
Передача массива как параметра в функцию





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский