Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2015.05.10;
Скачать: CL | DM;

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.006 c
15-1411392772
achiz
2014-09-22 17:32
2015.05.10
Стоимость программа для базы данных агентства недвижимости


15-1411666339
Rouse_
2014-09-25 21:32
2015.05.10
Новые правила для конференции "Прочее"


2-1392352421
lewka
2014-02-14 08:33
2015.05.10
SQL и DataSource


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


15-1411460309
Problem
2014-09-23 12:18
2015.05.10
Вопрос по настройке Delphi 2007