我想检测一个IP的指定端口是否开放!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

时间:2020-12-30 15:20:02
我想检测一个IP的指定端口是否开放,那么我连一下就知道了,
连上了就是开放,并且断开连接。连不上就是没有开放。

但是我又不想用控件,想直接用API,找到了如下代码,测试了没有效果,怎么连都是False;

function ScanTCPPort(ipstr : string; Port: DWORD): Boolean;
var
  option: DWORD;
  TcpSock: TSocket;
  InAddr: TSockAddrIn;
  IP : DWORD;
begin
  result := False;
  
  //convert IP string to ulong
  IP := ntohl(inet_addr(PChar(ipstr)));
  if IP = INADDR_NONE then  //invalid IP address!
    exit;
  
  // Create/open a socket (stream, not datagram)
  TcpSock := socket(AF_INET, SOCK_STREAM, 0);
  if TcpSock = INVALID_SOCKET then  //socket error
    exit;
    
  try
    // Set socket options
    option := 0;
    setsockopt(TcpSock, SOL_SOCKET, SO_KEEPALIVE, @option, sizeof(option));
    option := 1;
    setsockopt(TcpSock, SOL_SOCKET, SO_DONTLINGER, @option, sizeof(option));
    
    //if winsock 1.1, including the next sentence, otherwise, skip it.
    setsockopt(TcpSock, IPPROTO_TCP, TCP_NODELAY, @option, sizeof(option));
    
    //Initialize address structure
    ZeroMemory(@InAddr, sizeof(InAddr));
    InAddr.sin_family := AF_INET;
    InAddr.sin_addr.S_addr := ntohl(IP);
    InAddr.sin_port := htons(Port);
    //Try to connect
    Result := connect(TcpSock, InAddr, sizeof(InAddr)) = 0;
  finally
    //Close the socket
    closesocket(TcpSock);
  end;
end;






调用  if ScanTCPPort('110.75.161.108',16000) then ShowMessage('True') else ShowMessage('False');

我Telnet是连的上的...

谁帮忙改一下上面那个Function,或者给个更好的Function

要源码,测试可用马上结贴


我Delphi7

12 个解决方案

#1


Function TryIPPort(Const IP : AnsiString; Port : integer) : Boolean;
var
  Sock : TSocket;
  SA   : TSockaddr;
  n , ul : integer;
  TV : TTimeVal;
  FDSet : TFDSet;
begin
  FillChar(SA , SizeOf(SA) , 0);
  SA.sin_family      := AF_INET;
  SA.sin_port        := htons(Port);
  SA.sin_addr.S_addr := inet_addr(Pointer(IP));
  Sock               := Socket(AF_INET , SOCK_STREAM , IPPROTO_IP);
  Result             := Sock<>invalid_socket;
  if Result then begin
    n := 3 * 1000;  //3秒超时
    ul := 1;
    if (SetSockopt(Sock , SOL_SOCKET , SO_SNDTIMEO , @n , SizeOf(n))<>SOCKET_ERROR) and
       (SetSockopt(Sock , SOL_SOCKET , SO_RCVTIMEO , @n , SizeOf(n))<>SOCKET_ERROR) and
       (ioctlsocket(Sock, FIONBIO, ul)<>SOCKET_ERROR) then begin
      Connect(Sock , SA , SizeOf(SA));
      FD_ZERO(FDSet);
      FD_SET(Sock , FDSet);
      TV.tv_sec := piTimeOut;
      TV.tv_usec := 0;
      Result := select(0, NIL , @FDSet , NIL , @TV)>0;
    end;
    CloseSocket(Sock);
  end;
end;

#2


你是没有调用WSAStartup初始化,所以建立socket失败
参考:

uses WinSock;

function ScanTCPPort(ip: string; port: Word): Boolean;
var
  sin: sockaddr_in;
  li_socket, err: Integer;
  wVersionRequested: Word;
  wsaData: TWSAData;
begin
  Result := False;
  try
    wVersionRequested := MAKEWORD(2, 0);
    err := WSAStartup(wVersionRequested, wsaData);
    if ( err <> 0 ) then
      Exit;
    li_socket := socket(AF_INET,SOCK_STREAM, 0);
    if li_socket < 0 then
      Exit;

    ZeroMemory(@sin, sizeof(sin));
    sin.sin_family := AF_INET;
    sin.sin_addr.s_addr := inet_addr(PChar(ip));
    sin.sin_port := htons(port);
    if connect(li_socket, sin, sizeof(sin)) < 0 then
      Exit;
  finally
    closesocket(li_socket);
  end;
  Result := True;
end;

#3


回1楼,代码测试不可用,也是怎么连都是false



回2楼  代码测试可用,请教怎么设置延迟?如果3秒延迟则放弃(放弃认为连不上)。

#4


刚搞错了

2楼代码也不可用,不管连什么都是返回 True

#5


你不会没WSAStartup吧?
完整代码在这里
http://blog.csdn.net/kiboisme/article/details/6573984

#6


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,Winsock;

type
  TForm1 = class(TForm)
    Button2: TButton;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  piTimeOut:integer=3; //延迟

Function TryIPPort(Const IP : AnsiString; Port : integer) : Boolean;
var
  Sock : TSocket;
  SA   : TSockaddr;
  n , ul : integer;
  TV : TTimeVal;
  FDSet : TFDSet;
begin
  FillChar(SA , SizeOf(SA) , 0);
  SA.sin_family      := AF_INET;
  SA.sin_port        := htons(Port);
  SA.sin_addr.S_addr := inet_addr(Pointer(IP));
  Sock               := Socket(AF_INET , SOCK_STREAM , IPPROTO_IP);
  Result             := Sock<>invalid_socket;
  if Result then begin
    n := piTimeOut * 1000;  //3秒超时
    ul := 1;
    if (SetSockopt(Sock , SOL_SOCKET , SO_SNDTIMEO , @n , SizeOf(n))<>SOCKET_ERROR) and
       (SetSockopt(Sock , SOL_SOCKET , SO_RCVTIMEO , @n , SizeOf(n))<>SOCKET_ERROR) and
       (ioctlsocket(Sock, FIONBIO, ul)<>SOCKET_ERROR) then begin
      Connect(Sock , SA , SizeOf(SA));
      FD_ZERO(FDSet);
      FD_SET(Sock , FDSet);
      TV.tv_sec := piTimeOut;
      TV.tv_usec := 0;
      Result := select(0, NIL , @FDSet , NIL , @TV)>0;
    end;
    CloseSocket(Sock);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  WSA : TWSAData;
begin
  WSAStartup(MakeWord(2,2),WSA);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if TryIPPort('110.75.161.108',16000) then ShowMessage('True') else ShowMessage('False');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if TryIPPort('110.75.161.108',9999) then ShowMessage('True') else ShowMessage('False');   //应该连不上的,他提示True
end;
    //这个IP110.75.161.108 的16000是开放的   9999端口是关闭的  ,但是怎么连都返回True ,不信你试一下
end.






不信你看。。。。。。。。。。。。。

#7


该回复于2012-05-04 08:42:13被版主删除

#8


求解答,代码在6楼

#9


UP`````````````````````````````

#10


即使我用你的代码,在D7和D2010上面都运行了,都能正确反应情况,你要考虑你的环境了.!

#11


我WINXP SP3

#12


我也遇到六楼的问题了,无论对方机器端口开没开(甚至关着机呢),都能返回true

#1


Function TryIPPort(Const IP : AnsiString; Port : integer) : Boolean;
var
  Sock : TSocket;
  SA   : TSockaddr;
  n , ul : integer;
  TV : TTimeVal;
  FDSet : TFDSet;
begin
  FillChar(SA , SizeOf(SA) , 0);
  SA.sin_family      := AF_INET;
  SA.sin_port        := htons(Port);
  SA.sin_addr.S_addr := inet_addr(Pointer(IP));
  Sock               := Socket(AF_INET , SOCK_STREAM , IPPROTO_IP);
  Result             := Sock<>invalid_socket;
  if Result then begin
    n := 3 * 1000;  //3秒超时
    ul := 1;
    if (SetSockopt(Sock , SOL_SOCKET , SO_SNDTIMEO , @n , SizeOf(n))<>SOCKET_ERROR) and
       (SetSockopt(Sock , SOL_SOCKET , SO_RCVTIMEO , @n , SizeOf(n))<>SOCKET_ERROR) and
       (ioctlsocket(Sock, FIONBIO, ul)<>SOCKET_ERROR) then begin
      Connect(Sock , SA , SizeOf(SA));
      FD_ZERO(FDSet);
      FD_SET(Sock , FDSet);
      TV.tv_sec := piTimeOut;
      TV.tv_usec := 0;
      Result := select(0, NIL , @FDSet , NIL , @TV)>0;
    end;
    CloseSocket(Sock);
  end;
end;

#2


你是没有调用WSAStartup初始化,所以建立socket失败
参考:

uses WinSock;

function ScanTCPPort(ip: string; port: Word): Boolean;
var
  sin: sockaddr_in;
  li_socket, err: Integer;
  wVersionRequested: Word;
  wsaData: TWSAData;
begin
  Result := False;
  try
    wVersionRequested := MAKEWORD(2, 0);
    err := WSAStartup(wVersionRequested, wsaData);
    if ( err <> 0 ) then
      Exit;
    li_socket := socket(AF_INET,SOCK_STREAM, 0);
    if li_socket < 0 then
      Exit;

    ZeroMemory(@sin, sizeof(sin));
    sin.sin_family := AF_INET;
    sin.sin_addr.s_addr := inet_addr(PChar(ip));
    sin.sin_port := htons(port);
    if connect(li_socket, sin, sizeof(sin)) < 0 then
      Exit;
  finally
    closesocket(li_socket);
  end;
  Result := True;
end;

#3


回1楼,代码测试不可用,也是怎么连都是false



回2楼  代码测试可用,请教怎么设置延迟?如果3秒延迟则放弃(放弃认为连不上)。

#4


刚搞错了

2楼代码也不可用,不管连什么都是返回 True

#5


你不会没WSAStartup吧?
完整代码在这里
http://blog.csdn.net/kiboisme/article/details/6573984

#6


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,Winsock;

type
  TForm1 = class(TForm)
    Button2: TButton;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  piTimeOut:integer=3; //延迟

Function TryIPPort(Const IP : AnsiString; Port : integer) : Boolean;
var
  Sock : TSocket;
  SA   : TSockaddr;
  n , ul : integer;
  TV : TTimeVal;
  FDSet : TFDSet;
begin
  FillChar(SA , SizeOf(SA) , 0);
  SA.sin_family      := AF_INET;
  SA.sin_port        := htons(Port);
  SA.sin_addr.S_addr := inet_addr(Pointer(IP));
  Sock               := Socket(AF_INET , SOCK_STREAM , IPPROTO_IP);
  Result             := Sock<>invalid_socket;
  if Result then begin
    n := piTimeOut * 1000;  //3秒超时
    ul := 1;
    if (SetSockopt(Sock , SOL_SOCKET , SO_SNDTIMEO , @n , SizeOf(n))<>SOCKET_ERROR) and
       (SetSockopt(Sock , SOL_SOCKET , SO_RCVTIMEO , @n , SizeOf(n))<>SOCKET_ERROR) and
       (ioctlsocket(Sock, FIONBIO, ul)<>SOCKET_ERROR) then begin
      Connect(Sock , SA , SizeOf(SA));
      FD_ZERO(FDSet);
      FD_SET(Sock , FDSet);
      TV.tv_sec := piTimeOut;
      TV.tv_usec := 0;
      Result := select(0, NIL , @FDSet , NIL , @TV)>0;
    end;
    CloseSocket(Sock);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  WSA : TWSAData;
begin
  WSAStartup(MakeWord(2,2),WSA);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if TryIPPort('110.75.161.108',16000) then ShowMessage('True') else ShowMessage('False');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if TryIPPort('110.75.161.108',9999) then ShowMessage('True') else ShowMessage('False');   //应该连不上的,他提示True
end;
    //这个IP110.75.161.108 的16000是开放的   9999端口是关闭的  ,但是怎么连都返回True ,不信你试一下
end.






不信你看。。。。。。。。。。。。。

#7


该回复于2012-05-04 08:42:13被版主删除

#8


求解答,代码在6楼

#9


UP`````````````````````````````

#10


即使我用你的代码,在D7和D2010上面都运行了,都能正确反应情况,你要考虑你的环境了.!

#11


我WINXP SP3

#12


我也遇到六楼的问题了,无论对方机器端口开没开(甚至关着机呢),都能返回true