如何检查Delphi的TCP端口是否可用?

时间:2010-01-28 16:37:57

标签: delphi tcp

除了捕获netstat调用之外,是否有一种更优雅的方式来检查Delphi是否可以使用TCP端口?

6 个答案:

答案 0 :(得分:7)

我猜你可以使用Indy的组件来做到这一点。例如,如果端口在打开时正在使用,TIdHTTPServer将引发异常。

所以基本上你可以创建这样的组件,将它绑定到localhost:<yourport>,如果引发异常(捕获它并检查它),那么端口可能正在使用,否则它是免费的。

我猜其他indy组件可以判断端口是否打开,但我现在无法查看它。

这只是为了给你一个方法。

答案 1 :(得分:6)

@Mattl,如果可用意味着您可以使用,则可以使用此代码。

program CheckTCP_PortOpen;

{$APPTYPE CONSOLE}

uses
  Winsock; //Windows Sockets API Unit

    function PortTCPIsOpen(dwPort : Word; ipAddressStr:string) : boolean;
    var
      client : sockaddr_in;//sockaddr_in is used by Windows Sockets to specify a local or remote endpoint address
      sock   : Integer;
    begin
        client.sin_family      := AF_INET;
        client.sin_port        := htons(dwPort);//htons converts a u_short from host to TCP/IP network byte order.
        client.sin_addr.s_addr := inet_addr(PChar(ipAddressStr)); //the inet_addr function converts a string containing an IPv4 dotted-decimal address into a proper address for the IN_ADDR structure.
        sock  :=socket(AF_INET, SOCK_STREAM, 0);//The socket function creates a socket 
        Result:=connect(sock,client,SizeOf(client))=0;//establishes a connection to a specified socket.
    end;

var
  ret    : Integer;
  wsdata : WSAData;
begin
  Writeln('Init WinSock');
  ret := WSAStartup($0002, wsdata);//initiates use of the Winsock
  if ret<>0 then exit;
  try
    Writeln('Description : '+wsData.szDescription);
    Writeln('Status      : '+wsData.szSystemStatus);

    if PortTCPIsOpen(80,'127.0.0.1') then
    Writeln('Open')
    else
    Writeln('Close');

  finally
  WSACleanup; //terminates use of the Winsock
  end;

  Readln;
end.

答案 2 :(得分:4)

Synapse的以下代码非常有效:

uses
  blcksock;

function PortAvailable(Port:STring):boolean;
var
  svr : TTCPBlockSocket;
begin
  svr := TTCPBlockSocket.Create;
  try
    svr.Bind('0.0.0.0',Port);
    svr.Listen;
    result := svr.LastError = 0;
    Svr.CloseSocket;
  finally
    svr.Free;
  end;
end;

答案 3 :(得分:4)

可以通过调用IP Helper API或IPHLPAPI.DLL中的netstatGetTcpTable函数来检索

GetUdpTable信息。有关从Delphi调用IPHLPAPI.DLL的更多信息,请查看此Network traffic monitor。它也有一些wrappers,它是JEDI API Library的一部分。

很久以前我写了一个Delphi版的NetStat,但后来丢失了源代码。这些资源应该让你开始。

答案 4 :(得分:1)

使用Indy.Sockets v10 TIdTCPServer组件:

function TExample.IsTCPPortAvailable(const APort: Word): Boolean;
var
  LTCPServer: TIdTCPServer;
  LBinding: TIdSocketHandle;
begin
  Result := True;

  LTCPServer := TIdTCPServer.Create;
  try
    try
      with LTCPServer do
      begin
        DefaultPort   := APort;
        LBinding      := Bindings.Add;
        LBinding.IP   := '127.0.0.1';
        LBinding.Port := APort;
        OnExecute     := TCPServerExecute;
        Active        := True;
      end;
    finally
      LTCPServer.Free;
    end;
  except on EIdCouldNotBindSocket do
    Result := False;
  end;
end;

procedure TExample.TCPServerExecute(AContext: TIdContext);
begin
end;

答案 5 :(得分:0)

基于上述Silver的示例,并且由于在许多情况下,您想要查找可用端口而不是仅验证给定端口正在使用中:

uses
  //Indy V10
  IdContext,
  IdSocketHandle,
  IdTcpServer;

type
  //our port-checking tool
  TPortChk = class(TIdTCPServer)
    procedure OnExec(AContext: TIdContext);
  end;

procedure TPortChk.OnExec(AContext: TIdContext);
begin
  //does nothing, but must exist and be hooked
end;

//check a TCP port to see if it's already in use.
//normally used before opening a listener.
function PortAvailable(APort: Word): Boolean;
var
  svr: TPortChk;
  bnd: TIdSocketHandle;
begin
  //assume our port is available
  Result := True;
  //create our checking object
  svr := TPortChk.Create;
  try
    //set the execute event
    svr.OnExecute := svr.OnExec;
    //loop looking for an available port
    try
      //set up the binding for our local system and the
      //port in question
      bnd := svr.Bindings.Add;
      bnd.IP := '127.0.0.1';
      bnd.Port := APort;
      //try to bind.  This will throw an EIdCouldNotBindSocket
      //exception if the port is already in use.
      svr.Active := True;
      //if we get here, the port is *currently* available.
      //close the server and bail
      svr.Active := False;
      Exit;
    except
      //whoops, port's in use (or some related failure)
      Result := False;
    end;
  finally
    svr.Free;
  end;
end;

//search a range of ports for the first available
function FindAvailablePort(First, Count: Word): Word;
var
  svr: TPortChk;
  bnd: TIdSocketHandle;
begin
  //assume our initial port is available
  Result := First;
  //create our checking object
  svr := TPortChk.Create;
  try
    //set the execute event
    svr.OnExecute := svr.OnExec;
    //loop looking for an available port
    while (Result - First) < Count do begin
      try
        //set up the binding for our local system and the
        //port in question
        bnd := svr.Bindings.Add;
        bnd.IP := '127.0.0.1';
        bnd.Port := Result;
        //try to bind.  This will throw an EIdCouldNotBindSocket
        //exception if the port is already in use.
        svr.Active := True;
        //if we get here, we found our available port, so kill the
        //server and bail
        svr.Active := False;
        Exit;
      except
        Inc(Result);
        svr.Bindings.Clear;
      end;
    end;
    //if we get here, all of our possible ports are in use,
    //so return $FFFF to indicate that no port is available
    Result := $FFFF;
  finally
    svr.Free;
  end;
end;