获取当前机器上首个未使用的 TCP 端口

这个函数用于获取计算机上首个未使用的 TCP 端口以便程序使用。有时候我们并不需要一个固定的端口来提供服务,通过这个函数,我们就可以找到一个可用的端口了。这个函数如果返回 0 ,则没有任何可用的端口(几率几乎为 0 吧?),同样的方法也可以用于获取可用的 UDP 端口,换个函数而已。

uses IpRtrMib, Iphlpapi, winsock;

function GetFirstUnusedTcpPort(ADefPort: Word): Word;
var
  ATables: PMIB_TCPTABLE;
  ASize: DWORD;
  Addr: TInAddr;
  I: Integer;
  AUsedPorts: array [0 .. 8191] of Byte;
begin
  ASize := 0;
  Result := 0; // 无效
  if ADefPort=0 then
     ADefPort:=GetCurrentProcessId;
  if GetTcpTable(nil, ASize, True) = ERROR_INSUFFICIENT_BUFFER then
  begin
    GetMem(ATables, ASize);
    try
      if GetTcpTable(ATables, ASize, True) = NO_ERROR then
      begin
        FillChar(AUsedPorts, 8192, 0);
        for I := 0 to ATables.dwNumEntries - 1 do
        begin
          ASize := ntohs(ATables.table[I].dwLocalPort);
          AUsedPorts[ASize shr 3] := AUsedPorts[ASize shr 3] or
            (1 shl (ASize and $7));
        end;
        for Result := ADefPort to 65535 do
        begin
          if (AUsedPorts[Result shr 3] and (1 shl (Result and $7))) = 0 then
            Exit;
        end;
        for I := 1 to Result-1 do
          begin
          if (AUsedPorts[Result shr 3] and (1 shl (Result and $7))) = 0 then
            Exit;
          end;
        Result:=0;
      end;
    finally
      FreeMem(ATables);
    end;
  end;
end;

参数是默认的端口号,如果这个端口号没被占用,则会被返回,如果被占用了,则返回其它值。

分享到: