Соединяюсь с сокетом через функцию Connect Если сервер не отвечает, то есть не удалось к нему подключится, через некоторое время (причем почему-то все время разное, в промежутке 20-120сек) функция возвращает код ошибки. Собственно вопрос: Возможно ли как-то указать свое время соединения, после истечении которого произошел бы выход из функции Connect? Яп: дельфи.
Неплохо было бы указать язык программирования, который ты используешь. Как правило можно всегда, задается в одном из следующих мест: 1. конфигурационный файл (значение по умолчанию), для скриптовых языков 2. параметры, опции сокета 3. необязательный параметр в функции (методе) connect
AFAIK в API сокетов нет опций именно для таймаута на connect (есть таймауты на send и recv, но утверждений что оно распространяется и на connect не дается). Более-менее надежное решение проблемы под windows 1. Создать сокет 2. Создать дескриптор для события, через который мы узнаем о завершении операции connect (создается вызовом WSACreateEvent) 3. Использовать WSAEventSelect для привязки созданного дескриптора к сокету, на отслеживание FD_CONNECT 4. Забиндить сокет и перевести его в неблокирующий режим (делается через ioctlsocket) 5. Инициировать connect и проверить, что оно вернуло WSAEWOULDBLOCK. 6. Вызвать WaitForSingleObject с ранее созданным событием и задать там таймаут. Должно вернуть WAIT_OBJECT_0 в случае возбуждения события и WAIT_TIMEOUT в случае истечения времени. Далее закрыть дескриптор события и перевести сокет обратно в блокирующий режим, если нужно. Еще можно вместо событий вызывать select, там тоже есть возможность задать таймаут на готовность к чтению/записи.
У меня получился такой код: Code: var hEvent: Thandle; s:Tsocket; addr: Tsockaddr; Sock: TWSAData; block:boolean; s1,s2:string; Reason:DWORD; begin WSAStartup(MAKEWORD(2,2),sock); hEvent:=WSACreateEvent(); WSAEventSelect(s, hEvent, FD_CONNECT); s:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); FillChar(addr, SizeOf(sockaddr_in), 0); addr.sin_family:=AF_Inet; addr.sin_port:=htons(80); addr.sin_addr.S_addr:=inet_addr(Pchar('77.88.21.3')); bind(s, addr, SizeOf(TSockAddrin)); block:=true; ioctlsocket(s, FIONBIO, cardinal(block)); Reason:=WaitForSingleObject(hEvent, 1000); if Reason = WAIT_TIMEOUT then showmessage('no connect'); if Reason = WAIT_OBJECT_0 then showmessage('connect'); Ошибка на строке bind(s, addr, SizeOf(TSockAddrin)); : Incompatible types: 'TSockAddrIn' and 'PSockAddr' Если поменять addr: Tsockaddr; на addr: Зsockaddr; - компилируется, но при выполнении Крит. ошибка доступа к области памяти на строке addr.sin_family:=AF_Inet; Подскажите, как исправить эту проблему.
Может быть нужно сначала создать сокет, а уже потом привязывать к нему событие? Именно так написали постом выше. У твоем коде вместо bind должен быть connect. Получить PSockAddr (указатель на TSockAddr) можно так: @addr. Здесь в событиях нет нужды, лучше select использовать.