Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows Delphi:尝试查找打开的TCP端口,但没有';检测不到任何打开的端口_Windows_Delphi_Sockets_Ports - Fatal编程技术网

Windows Delphi:尝试查找打开的TCP端口,但没有';检测不到任何打开的端口

Windows Delphi:尝试查找打开的TCP端口,但没有';检测不到任何打开的端口,windows,delphi,sockets,ports,Windows,Delphi,Sockets,Ports,我有两个进程必须在PC上的两个空闲TCP端口上运行。这对于它的用户来说一定是一个无痛的开箱即用进程,我想自动检测空闲端口以避免冲突,并将这些端口号应用于这两个进程 为了实现这一点,我创建了一个函数(也在线程中运行)来检测空闲端口,但没有找到任何空闲端口。有人能解释一下我的代码有什么问题吗 编辑:将“@500错误等”提供的解决方案应用于代码。功能正常。 这是: uses winsock; type TAvailablePortArray = array of

我有两个进程必须在PC上的两个空闲TCP端口上运行。这对于它的用户来说一定是一个无痛的开箱即用进程,我想自动检测空闲端口以避免冲突,并将这些端口号应用于这两个进程

为了实现这一点,我创建了一个函数(也在线程中运行)来检测空闲端口,但没有找到任何空闲端口。有人能解释一下我的代码有什么问题吗

编辑:将“@500错误等”提供的解决方案应用于代码。功能正常。

这是:

    uses
     winsock;

    type
     TAvailablePortArray = array of Word;

function findAvailableTCPPort( ipAddressStr : String; portStart : Word = 8080; portEnd : Word = 8084; findCount : Byte = 2 ) : TAvailablePortArray;
var
  client    : sockaddr_in;
  sock      : Integer;
  ret       : Integer;
  wsdata    : WSAData;
  dwPort    : Word;
  iFound    : Byte;
  bResult   : Boolean;
  bAllFound : Boolean;
  dns       : PHostEnt;
  status    : LongInt;


begin
 setLength( Result, 0 );
 if( portStart > portEnd ) or ( portStart = 0 ) or ( findCount = 0 ) then
  Exit;

 try
 ret := WSAStartup($0002, wsdata); //initiates use of the Winsock DLL
 except
  ret:=-1;
 end;

 if( ret <> 0 ) then
  Exit;

 dns:=getHostByName( PChar(ipAddressStr) );
 if( NOT Assigned( dns )) then
  Exit;

 bResult:=TRUE;
 try
  fillChar( client, sizeOf( client ), 0 );
  client.sin_family      := AF_INET;  //Set the protocol to use , in this case (IPv4)
  client.sin_addr.s_addr :=LongInt(PLongInt(dns^.h_addr_list^)^);
  //inet_addr(PAnsiChar(ipAddressStr));  //convert to IN_ADDR  structure
 except
  bResult:=FALSE;
 end;

 if( bResult ) then
 begin
  dwPort:=portStart;
  setLength( Result, findCount );
  bAllFound:=FALSE;
  iFound:=0;

  while( NOT bAllFound ) and ( dwPort <= portEnd ) do
  begin
   try
    client.sin_port:=htons(dwPort); //convert to TCP/IP network byte order (big-endian)
    sock:=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP );    //creates a socket
    Application.processMessages();
    status:=connect(sock,client,sizeOf(client));
    bResult:=(status <> 0); //establishes a connection to a specified socket, less than zero is NOT in use
   except
    bResult:=FALSE;
   end;

   if( sock <> 0 ) then
   begin
    closesocket(sock);
    sock:=0;
   end; 

   if( bResult ) then
   begin
    Result[iFound]:=dwPort;
    inc( iFound );
    bAllFound:=( iFound = findCount );
   end;

   inc(dwPort);
  end;
 end;

 if( NOT bAllFound ) then
  setLength( Result, 0 );

 try
  WSACleanup();
 except;
 end;
end;
使用
温索克;
类型
TAvailablePortArray=字数组;
函数findAvailableTCPPort(ipAddressStr:String;portStart:Word=8080;portEnd:Word=8084;findCount:Byte=2):TAvailablePortArray;
变量
客户:sockaddr_in;
sock:整数;
ret:整数;
wsdata:WSAData;
dwPort:Word;
iFound:字节;
bResult:布尔型;
ballfund:布尔型;
dns:光能;
状态:LongInt;
开始
setLength(结果为0);
如果是(portStart>portEnd)或(portStart=0)或(findCount=0),则
出口
尝试
ret:=WSAStartup($0002,wsdata)//启动Winsock DLL的使用
除了
ret:=-1;
终止
如果(ret 0)那么
出口
dns:=getHostByName(PChar(ipAddressStr));
如果(未分配(dns)),则
出口
b结果:=真;
尝试
fillChar(客户端,sizeOf(客户端),0);
client.sinu family:=AF\u INET//设置要使用的协议(在本例中为IPv4)
client.sin_addr.s_addr:=LongInt(PLongInt(dns^.h_addr_list^));
//inet_地址(PAnsiChar(ipAddressStr))//转换为IN_ADDR结构
除了
b结果:=假;
终止
如果(bResult)那么
开始
dwPort:=portStart;
setLength(结果,findCount);
bAllFound:=假;
iFound:=0;
虽然(未找到)和(dwPortI(现在)认为问题在于您误解了
connect
的结果


如果
connect
成功(返回零),则表示端口正在使用中。

您使用的方法错误。您应该使用
bind()
而不是
connect()
。如果端口已在使用中,
bind()
将失败。无需尝试将
连接()
到单独的IP。例如:

uses
  winsock;

type
  TAvailablePortArray = array of Word;

function findAvailableTCPPort( const ipAddressStr : AnsiString; portStart : Word = 8080; portEnd : Word = 8084; findCount : Byte = 2 ) : TAvailablePortArray;
var
  client    : sockaddr_in;
  sock      : TSocket;
  wsdata    : WSAData;
  dwPort    : Word;
  iFound    : Byte;
  bResult   : Boolean;
  arrFound  : TAvailablePortArray;
begin
  SetLength( Result, 0 );
  if ( portStart = 0 ) or ( portStart > portEnd ) or ( findCount = 0 ) then
    Exit;

  //initiates use of the Winsock DLL
  if ( WSAStartup(MAKEWORD(2, 0), wsdata) <> 0 ) then
    Exit;

  try
    //Set the protocol to use , in this case (IPv4)
    fillChar( client, sizeOf( client ), 0 );
    client.sin_family      := AF_INET;
    client.sin_addr.s_addr := inet_addr(PAnsiChar(ipAddressStr));

    dwPort := portStart;
    SetLength( arrFound, findCount );
    try
      iFound := 0;

      repeat
        sock := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    //creates a socket
        if sock = INVALID_SOCKET then Break;

        try
          if GetQueueStatus(QS_ALLINPUT) <> 0 then
            Application.ProcessMessages();

          client.sin_port := htons(dwPort); //convert to TCP/IP network byte order (big-endian)

          if bind(sock, PSockAddr(@client)^, sizeOf(client)) = 0 then
          begin
            arrFound[iFound] := dwPort;
            Inc( iFound );
          end;
        finally
          closesocket(sock);
        end;

        Inc(dwPort);
      until ( iFound = findCount ) or ( dwPort > portEnd );
    finally
      SetLength(arrFound, iFound);
    end;
  finally
    WSACleanup();
  end;

  Result := arrFound;
end;
使用
温索克;
类型
TAvailablePortArray=字数组;
函数findAvailableTCPPort(const-ipaddress str:AnsiString;portStart:Word=8080;portEnd:Word=8084;findCount:Byte=2):TAvailablePortArray;
变量
客户:sockaddr_in;
短袜:短袜;
wsdata:WSAData;
dwPort:Word;
iFound:字节;
bResult:布尔型;
arrFound:TAvailablePortArray;
开始
SetLength(结果为0);
如果(portStart=0)或(portStart>portEnd)或(findCount=0),则
出口
//启动Winsock DLL的使用
如果(WSAStartup(MAKEWORD(2,0),wsdata)0),那么
出口
尝试
//设置要使用的协议(在本例中为IPv4)
fillChar(客户端,sizeOf(客户端),0);
client.sinu family:=AF\u INET;
client.sin_addr.s_addr:=inet_addr(PAnsiChar(ipAddressStr));
dwPort:=portStart;
设置长度(arrFound、findCount);
尝试
iFound:=0;
重复
sock:=套接字(AF_INET、sock_STREAM、IPPROTO_TCP);//创建套接字
如果插座=无效的插座,则断开;
尝试
如果GetQueueStatus(QS_ALLINPUT)为0,则
Application.ProcessMessages();
client.sin_port:=htons(dwPort);//转换为TCP/IP网络字节顺序(大端)
如果bind(sock,PSockAddr(@client)^,sizeOf(client))=0,则
开始
arrFound[iFound]:=dwPort;
公司(iFound);
终止
最后
插座;
终止
公司(dwPort),;
直到(iFound=findCount)或(dwPort>portEnd);
最后
设置长度(arrFound,iFound);
终止
最后
WSACleanup();
终止
结果:=arrFound;
终止
或者,完全忘记使用套接字。改为通过Windows的TCP/UDP表枚举,该表列出了正在使用的活动端口。查看、和


话虽如此,这两种方法都存在根本性的缺陷,因为这两种方法都有竞争条件——在函数找到可用端口后,其他人可能会在您的进程可以打开端口之前出现并打开端口。最好的选择是让每个进程
bind()
无条件地将自身连接到端口0,并让操作系统在此时选择一个可用的端口,然后这两个进程可以在需要时宣布其指定的端口。

您的解决方案不太科学,但您是对的!谢谢。当它未连接时,返回-1。您知道此代码的确切含义吗?请参阅。
socket()
返回
无效的\u套接字
(-1)关于错误,而不是0。关于向下投票:有时我不了解SO的人,为什么要向下投票我的问题,为什么?????头发不好?如果我使用bind,结果总是零。当我检查WSAGetLastError时,当端口正在使用时,返回值永远不会是WSAEADDRINUSE。所以我会错过一些固有的东西吗?当
bind()
返回零,表示指定的端口可供使用,现在已分配给绑定的套接字。
WSAGetLastError()
仅在发生错误时才有意义。这不是真实的故事。无论发生什么情况,bind函数始终返回零。使用在指定端口上运行的某些服务器进行测试,结果总是一样的。我向您保证,
bind()
无法绑定到已在使用的端口。它将报告
WSAEADDRINUSE
。唯一不会发生这种情况的方法是启用
SO\u REUSEADDR
选项,如果启用该选项,则不应执行该操作。您好,雷米,测试了您的功能,但它不工作。它告诉我8080端口是免费的,但它不是。
uses
  winsock;

type
  TAvailablePortArray = array of Word;

function findAvailableTCPPort( const ipAddressStr : AnsiString; portStart : Word = 8080; portEnd : Word = 8084; findCount : Byte = 2 ) : TAvailablePortArray;
var
  client    : sockaddr_in;
  sock      : TSocket;
  wsdata    : WSAData;
  dwPort    : Word;
  iFound    : Byte;
  bResult   : Boolean;
  arrFound  : TAvailablePortArray;
begin
  SetLength( Result, 0 );
  if ( portStart = 0 ) or ( portStart > portEnd ) or ( findCount = 0 ) then
    Exit;

  //initiates use of the Winsock DLL
  if ( WSAStartup(MAKEWORD(2, 0), wsdata) <> 0 ) then
    Exit;

  try
    //Set the protocol to use , in this case (IPv4)
    fillChar( client, sizeOf( client ), 0 );
    client.sin_family      := AF_INET;
    client.sin_addr.s_addr := inet_addr(PAnsiChar(ipAddressStr));

    dwPort := portStart;
    SetLength( arrFound, findCount );
    try
      iFound := 0;

      repeat
        sock := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    //creates a socket
        if sock = INVALID_SOCKET then Break;

        try
          if GetQueueStatus(QS_ALLINPUT) <> 0 then
            Application.ProcessMessages();

          client.sin_port := htons(dwPort); //convert to TCP/IP network byte order (big-endian)

          if bind(sock, PSockAddr(@client)^, sizeOf(client)) = 0 then
          begin
            arrFound[iFound] := dwPort;
            Inc( iFound );
          end;
        finally
          closesocket(sock);
        end;

        Inc(dwPort);
      until ( iFound = findCount ) or ( dwPort > portEnd );
    finally
      SetLength(arrFound, iFound);
    end;
  finally
    WSACleanup();
  end;

  Result := arrFound;
end;