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

Вниз

таймаут сокета   Найти похожие ветки 

 
tippa ©   (2010-06-09 16:12) [0]

Добрый день.
var info:TWSADATA;
   sock:TSocket;
   addr:sockaddr_in;
begin
WSAStartup(MAKEWORD(2,0),info);
sock:=socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family:=AF_INET;
addr.sin_addr.S_addr:=inet_addr("151.151.151.151");
addr.sin_port:=htons(80);
if connect(sock,@addr,sizeof(addr))=0 then showmessage("Yes")
                                     else showmessage("No");
end;

Код проверяет открыт ли порт на удаленной машине. Если адрес не доступен - то функция connect подвисает секунд на 20. Нужно указать таймаут скажем на 5 секунд. Вот нашел код
var
timeout:TTimeVal;
begin
timeout.tv_usec:=0;
timeout.tv_sec:=10000; // время задается в миллисекундах. 10000 = 10 секунд
// установим для сокета sock время ожидания чтения данных = 10 секунд.
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, @timeout, sizeof(ttimeval));

собственно та же картина, чего-то не хватает.
Хотелось бы самое простое решение, без перевода сокета в неблокирующий режим - если это возможно конечно.


 
tippa ©   (2010-06-09 18:48) [1]

о как
var info:TWSADATA;
   sock:TSocket;
   timeout:TTimeVal;
   addr:sockaddr_in;
   fds:TFDSet;
   rc:integer;
   block:bool;
begin
WSAStartup(MAKEWORD(2,0),info);
sock:=socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family:=AF_INET;
addr.sin_addr.S_addr:=inet_addr("151.151.151.151");
addr.sin_port:=htons(80);
block:=true;
ioctlsocket(sock, FIONBIO, cardinal(block));
connect(sock,@addr,sizeof(addr));
     FD_ZERO(fds)
     FD_SET(sock,fds);
     timeout.tv_sec:=1;
     timeout.tv_usec:=0;
     rc:=select(0, nil, @fds, nil, @timeout);
block:=false;
ioctlsocket(sock, FIONBIO, cardinal(block));
closesocket(sock);
if rc<>0 showmessage("Yes") else showmessage("No");
end;


 
DVM ©   (2010-06-09 20:51) [2]


> tippa ©   (09.06.10 18:48) [1]

а кто будет анализировать коды возврата функций


 
tippa ©   (2010-06-10 06:59) [3]

var info:TWSADATA;
  sock:TSocket;
  timeout:TTimeVal;
  addr:sockaddr_in;
  fds:TFDSet;
  rc:integer;
  block:bool;
begin
if WSAStartup(MAKEWORD(2,0),info)<>0 then
begin
showmessage("Error");
exit;
end;
sock:=socket(AF_INET, SOCK_STREAM, 0);
if sock=INVALID_SOCKET then
begin
showmessage("Error");
exit;
end;
addr.sin_family:=AF_INET;
addr.sin_addr.S_addr:=inet_addr("151.151.151.151");
addr.sin_port:=htons(80);
block:=true;
if ioctlsocket(sock, FIONBIO, cardinal(block))<>0 then
begin
showmessage("Error");
exit;
end;
if connect(sock,@addr,sizeof(addr))<>0 then
begin
showmessage("Error");
exit;
end;
    FD_ZERO(fds)
    FD_SET(sock,fds);
    timeout.tv_sec:=1;
    timeout.tv_usec:=0;
    rc:=select(0, nil, @fds, nil, @timeout);
block:=false;
if ioctlsocket(sock, FIONBIO, cardinal(block))<>0 then
begin
showmessage("Error");
exit;
end;
closesocket(sock);
if rc<>0 showmessage("Yes") else showmessage("No");
end;

так потянет?
и обязательно ли переводить сокет обратно в блокирующий режим, ведь все равно следующей строкой мы его закрываем?


 
tippa ©   (2010-06-10 08:27) [4]

а заместо
if connect(sock,@addr,sizeof(addr))<>0 then
оказалось надо
if connect(sock,@addr,sizeof(addr))=0 then


 
DVM ©   (2010-06-10 10:32) [5]


> tippa ©   (10.06.10 06:59) [3]


> и обязательно ли переводить сокет обратно в блокирующий
> режим

необязательно

Кроме этого select может возвращать 0, 1 и SOCKET_ERROR, ты же проверяешь только на неравенство 0, на вдруг SOCKET_ERROR. Затем, если select вернула 1, это еще не означает, что подключились, надо проверить не пустое ли множество fds. Еще желательно завести множество efd - оно должно быть пустое при успешном подключении: select(0, nil, @wfd, @efd, @TimeVal)

             case select(0, nil, @wfd, @efd, @TimeVal) of
               0: еще пока не подключились;
               1: if FD_ISSET(Result, wfd) then
                    вот тут подключились
                  else
                    if FD_ISSET(Result, efd) then
                      begin
                        а вот тут ошибка
                        exit;
                      end;
               SOCKET_ERROR:
                 begin
                   и тут ошибка
                   exit
                 end;


 
tippa ©   (2010-06-10 13:30) [6]

спасибо, вот еще
if connect(sock,@addr,sizeof(addr))<>0 then
begin
showmessage("Error");
exit;
end;

так как мы только что перевели сокет в неблокирующий режим, то connect всегда будет давать ошибку. Если эта ошибка WSAEWOULDBLOCK то сокет перешел в неблокирующий режим и все хорошо.
Вообщем как-то так.
var info:TWSADATA;
 sock:TSocket;
 timeout:TTimeVal;
 addr:sockaddr_in;
 fds,efd:TFDSet;
 rc:integer;
 block:bool;
begin
if WSAStartup(MAKEWORD(2,0),info)<>0 then exit;
sock:=socket(AF_INET, SOCK_STREAM, 0);
if sock=INVALID_SOCKET then exit;
addr.sin_family:=AF_INET;
addr.sin_addr.S_addr:=inet_addr("151.151.151.151");
addr.sin_port:=htons(80);
block:=true;
if ioctlsocket(sock, FIONBIO, cardinal(block))<>0 then exit;
connect(sock,@addr,sizeof(addr));
if WSAGetLastError<>WSAEWOULDBLOCK then exit;
   FD_ZERO(fds)
   FD_SET(sock,fds);
   timeout.tv_sec:=1;
   timeout.tv_usec:=0;
case select(0, nil, @fds, @efd, @TimeVal) of
0: exit;
1: if FD_ISSET(sock, fds) then showmessage("Yes");
   else
   if FD_ISSET(sock, efd) then exit;
SOCKET_ERROR: exit;
closesocket(sock);
end;

еще замечния?


 
DVM ©   (2010-06-10 22:56) [7]


> так как мы только что перевели сокет в неблокирующий режим,
>  то connect всегда будет давать ошибку.

ну почему всегда, если повезет, то может и сразу соединиться.


> еще замечния?

closesocket(sock); не будет вызываться в ряде случаев, а надо бы всегда, если вызов socket() был успешен. Try...Finally например добавь



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

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

Наверх





Память: 0.47 MB
Время: 0.002 c
2-1392205331
Коля
2014-02-12 15:42
2015.05.10
Запрос SQL


15-1411486735
Kerk
2014-09-23 19:38
2015.05.10
выбор NAS для дома для себя


2-1392309493
alexdn
2014-02-13 20:38
2015.05.10
Чтение из реестра


15-1411744010
Alarm
2014-09-26 19:06
2015.05.10
Без темы, обидно за форум


15-1411156060
Jeer
2014-09-19 23:47
2015.05.10
SAP





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский