-
Добрый день. 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; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, @timeout, sizeof(ttimeval)); собственно та же картина, чего-то не хватает. Хотелось бы самое простое решение, без перевода сокета в неблокирующий режим - если это возможно конечно.
-
о как 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;
-
> tippa © (09.06.10 18:48) [1]
а кто будет анализировать коды возврата функций
-
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; так потянет? и обязательно ли переводить сокет обратно в блокирующий режим, ведь все равно следующей строкой мы его закрываем?
-
а заместо if connect(sock,@addr,sizeof(addr))<>0 then оказалось надо if connect(sock,@addr,sizeof(addr))=0 then
-
> 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;
-
спасибо, вот еще 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; еще замечния?
-
> так как мы только что перевели сокет в неблокирующий режим, > то connect всегда будет давать ошибку.
ну почему всегда, если повезет, то может и сразу соединиться.
> еще замечния?
closesocket(sock); не будет вызываться в ряде случаев, а надо бы всегда, если вызов socket() был успешен. Try...Finally например добавь
|