我想检测一个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

解决方案 »

  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;interfaceuses
      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.   

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