根据端口查找占用进程——API方法

转自http://blog.csdn.net/tht2009/article/details/40458425

在开发联网应用时,常常需要申请、绑定端口,这时就需判断哪些端口可用或指定端口是否被占用。在命令行窗口下,输入“netstat -ano"命令可以显示查看当前端口占用情况。如何在程序代码中实现这个功能呢?

当然也可以执行cmd命令,通过分析返回文本来判断。其实,Windows已经提供了获取当前网络连接状态的API,这些API都位于动态库Iphlpapi.dll中。跟查看端口情况相关的API主要有GetTcpTable、GetUdpTable、GetExtendedTcpTable、GetExtendedUdpTable,这四个API可以获取当前系统TCP、UDP端口连接表,后两个分别是前两个的扩展版,可以获得当前端口的占用进程ID。

1、GetExtendedTcpTable

函数原型如下:

DWORD GetExtendedTcpTable(
  _Out_    PVOID pTcpTable,
  _Inout_  PDWORD pdwSize,
  _In_     BOOL bOrder,
  _In_     ULONG ulAf,
  _In_     TCP_TABLE_CLASS TableClass,
  _In_     ULONG Reserved
);

参数:

pTcpTable(指针类型): 存储TCP端口连接信息表,具体结构类型根据ulAF和TableClass参数而定。

pdwSize(传址):pTcpTable指向的内存大小,如果pdwSize比需要的空间小,函数返回一个ERROR_INSUFFICIENT_BUFFER错误,并将pdwSize 置为所需大小。

bOrder(布尔): 返回结果是否排序。

ulAF(整数):IP类型。AF_INET——IPv4; AF_INET6——IPv6。

       TableClass(枚举): TCP_TABLE_CLASS 。根据ulAF,传入相应不同值,返回的pTcpTable中结构类型不同。

              

typedef enum  {
  TCP_TABLE_BASIC_LISTENER,
  TCP_TABLE_BASIC_CONNECTIONS,
  TCP_TABLE_BASIC_ALL,
  TCP_TABLE_OWNER_PID_LISTENER,
  TCP_TABLE_OWNER_PID_CONNECTIONS,
  TCP_TABLE_OWNER_PID_ALL,
  TCP_TABLE_OWNER_MODULE_LISTENER,
  TCP_TABLE_OWNER_MODULE_CONNECTIONS,
  TCP_TABLE_OWNER_MODULE_ALL
} TCP_TABLE_CLASS, *PTCP_TABLE_CLASS;

      Reserved(保留):设为0。

转自http://blog.csdn.net/tht2009/article/details/40458425

pTcpTable指向结构类型与ulAF和TableClass取值关系如下:

ulAF value TableClass value pTcpTable structure
AF_INET TCP_TABLE_BASIC_ALL MIB_TCPTABLE
TCP_TABLE_BASIC_CONNECTIONS MIB_TCPTABLE
TCP_TABLE_BASIC_LISTENER MIB_TCPTABLE
TCP_TABLE_OWNER_MODULE_ALL MIB_TCPTABLE_OWNER_MODULE
TCP_TABLE_OWNER_MODULE_CONNECTIONS MIB_TCPTABLE_OWNER_MODULE
TCP_TABLE_OWNER_MODULE_LISTENER MIB_TCPTABLE_OWNER_MODULE
TCP_TABLE_OWNER_PID_ALL MIB_TCPTABLE_OWNER_PID
TCP_TABLE_OWNER_PID_CONNECTIONS MIB_TCPTABLE_OWNER_PID
TCP_TABLE_OWNER_PID_LISTENER MIB_TCPTABLE_OWNER_PID
AF_INET6 TCP_TABLE_OWNER_MODULE_ALL MIB_TCP6TABLE_OWNER_MODULE
TCP_TABLE_OWNER_MODULE_CONNECTIONS MIB_TCP6TABLE_OWNER_MODULE
TCP_TABLE_OWNER_MODULE_LISTENER MIB_TCP6TABLE_OWNER_MODULE
TCP_TABLE_OWNER_PID_ALL MIB_TCP6TABLE_OWNER_PID
TCP_TABLE_OWNER_PID_CONNECTIONS MIB_TCP6TABLE_OWNER_PID
TCP_TABLE_OWNER_PID_LISTENER MIB_TCP6TABLE_OWNER_PID

2、GetExtendedUdpTable

函数原型如下:

DWORD GetExtendedUdpTable(
  _Out_    PVOID pUdpTable,
  _Inout_  PDWORD pdwSize,
  _In_     BOOL bOrder,
  _In_     ULONG ulAf,
  _In_     UDP_TABLE_CLASS TableClass,
  _In_     ULONG Reserved
);

参数:

pUdpTable(指针类型): 存储UDP端口连接信息表,具体结构类型根据ulAF和TableClass参数而定。

pdwSize、bOrder、ulAF、Reserved:同TCP部分描述。

       TableClass(枚举): UDP_TABLE_CLASS 。根据ulAF,传入相应不同值,返回的pUdpTable中结构类型不同。

typedef enum  {
  UDP_TABLE_BASIC,
  UDP_TABLE_OWNER_PID,
  UDP_TABLE_OWNER_MODULE
} UDP_TABLE_CLASS, *PUDP_TABLE_CLASS;

pUdpTable指向结构类型与ulAF和TableClass取值关系如下:

ulAF value TableClass value pUdpTable structure
AF_INET UDP_TABLE_BASIC MIB_UDPTABLE
UDP_TABLE_OWNER_MODULE MIB_UDPTABLE_OWNER_MODULE
UDP_TABLE_OWNER_PID MIB_UDPTABLE_OWNER_PID
AF_INET6 UDP_TABLE_BASIC MIB_UDP6TABLE
UDP_TABLE_OWNER_MODULE MIB_UDP6TABLE_OWNER_MODULE
UDP_TABLE_OWNER_PID MIB_UDP6TABLE_OWNER_PID

根据上面介绍,可以很容易写出查看占用端口的进程功能:FindPidByTcpPort和FindPidByUdpPort函数。主要Delphi实现代码如下:

  /// <summary>通过指定TCP端口查找占用进程PID</summary>
  /// <param name="port :Integer">TCP端口号</param>
  /// <returns>Integer: -1,执行出错;0,指定端口未被占用;>0,占用进程PID</returns>
  function FindPidByTcpPort(port: Cardinal): Integer;

  /// <summary>通过指定UDP端口查找占用进程PID</summary>
  /// <param name="port :Integer">UDP端口号</param>
  /// <returns>Integer: -1,执行出错;0,指定端口未被占用;>0,占用进程PID</returns>
  function FindPidByUdpPort(port: Cardinal): Integer;

转自http://blog.csdn.net/tht2009/article/details/40458425

function FindPidByTcpPort(port: Cardinal): Integer;
var
  pTcpTable: PMibTcpTableOwnerPID;
  dwSize: DWORD;
  i: Integer;
begin
  Result := -1;
  dwSize := 0;
  //查询大小
  if GetExtendedTcpTable(nil, dwSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)
    = ERROR_INSUFFICIENT_BUFFER then
  begin
    pTcpTable := AllocMem(dwSize);
    //获取TCP连接表
    if GetExtendedTcpTable(pTcpTable, dwSize, True, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)
      =NO_ERROR then
    begin
      port := htons(port);

      for I := 0 to pTcpTable.dwNumEntries do
      begin
        if pTcpTable.table[i].dwLocalPort = Port then
        begin
          Result := pTcpTable.table[i].dwOwningPid;
          Break;
        end;
      end;

      if Result<0 then
         Result := 0;
    end;
    FreeMem(pTcpTable);
  end;
end;

function FindPidByUdpPort(port: Cardinal): Integer;
var
  pUdpTable: PMibUdpTableOwnerPID;
  dwSize: DWORD;
  i: Integer;
begin
  Result := -1;
  dwSize := 0;
  //查询大小
  if GetExtendedUdpTable(nil, dwSize, FALSE, AF_INET, UDP_TABLE_OWNER_PID, 0)
    = ERROR_INSUFFICIENT_BUFFER then
  begin
    pUdpTable := AllocMem(dwSize);
    //获取UDP连接表
    if GetExtendedUdpTable(pUdpTable, dwSize, True, AF_INET, UDP_TABLE_OWNER_PID, 0)
      =NO_ERROR  then
    begin
      port := htons(port);

      for I := 0 to pUdpTable.dwNumEntries do
      begin
        if pUdpTable.table[i].dwLocalPort = Port then
        begin
          Result := pUdpTable.table[i].dwOwningPid;
          Break;
        end;
      end;

      if Result<0 then
         Result := 0;
    end;
    FreeMem(pUdpTable);
  end;
end;

其中声明这两个函数,定义MibUdpTableOwnerPID与MibTcpTableOwnerPID结构体部分请参照MSDN中介绍,也可下载完整代码IpHlpApi2.pas查阅:http://www.colafile.com/file/2413129

转自http://blog.csdn.net/tht2009/article/details/40458425

时间: 2024-10-10 04:16:56

根据端口查找占用进程——API方法的相关文章

windows 80端口被占用的解决方法

参考文献: 文献1: http://wenku.baidu.com/view/af4681bcfd0a79563c1e7289.html 文献2: http://www.2cto.com/os/201111/111269.html 文献3: http://wenku.baidu.com/view/af4681bcfd0a79563c1e7289.html 文献4: http://www.cameroncooke.com/2009/01/25/windows-7-uses-port-80-and-

win8 64下启动Apache失败:443端口被占用的解决方法

今天帮朋友弄一个Apache的环境,遇到了The requested operation has failed的错误. 使用命令行启动之后报如下错误: D:\Apache24\bin>httpd -k start(OS 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次. : AH00072: make_sock: could not bind to address [::]:443(OS 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次. : AH0007

端口被占用的处理方法

开始--运行--cmd 进入命令提示符 输入netstat -ano 即可看到所有连接的PID 之后在任务管理器中找到这个PID所对应的程序如果任务管理器中没有PID这一项,可以在任务管理器中选"查看"-"选择列" 经常,我们在启动应用的时候发现系统需要的端口被别的程序占用,如何知道谁占有了我们需要的端口,很多人都比较头疼,下面就介绍一种非常简单的方法,希望对大家有用 假如我们需要确定谁占用了我们的9050端口 1.Windows平台 在windows命令行窗口下执

ApacheServer-----关于443端口被占用的解决方法

最经公司项目需要经过Apache服务器转发,自己也下载了ApacheServer,但是在启动的过程中,遇到443端口被占用,网上看了一些解决方法,都不对,没有解决问题. 执行启动命令httpd -k start  (出现443 端口被占用的情况) 自己查看了端口,netstat -aon|findstr "443" 然后查看 该pid  属于哪一个进程(从而知道,是哪一个进程占用的端口443) 发现是svn服务器占用了端口,以lz 的性格,不会委屈求全,(怎么也要让两个程序都正常的运行

phpstudy 80端口被占用的解决方法

1.执行httpd.exe  D:\phpStudy\PHPTutorial\Apache\bin>httpd.exe   返回 could not bind to address 0.0.0.0:80 显示80端口被占用 2.cmd netstat -ano |findstr "80"  查看进程id 4 3.在任务管理器里面发现 进程id为4  的为 NT kernel & System 4.下面是关闭NT kernel & System 的方法: 原文地址:

老男孩教育每日一题-第101天-如何通过端口查找出进程所在目录?

参考答案: 第一步-找到端口对应的进程的号 [[email protected] ~]# ss -lntup |grep :22 tcp    LISTEN     0      128                   :::22                   :::*      users:(("sshd",1467,4)) tcp    LISTEN     0      128                    *:22                    *:*

Windows查看某个端口被占用的解决方法

1.开始---->运行---->cmd,调出命令窗口.2.输入命令:netstat -ano,列出所有端口的情况.在列表中我们观察被占用的端口,比如是49153,首先找到它.3.查看被占用端口对应的PID,输入命令:netstat -aon|findstr "49153",回车,记下最后一位数字,即PID,这里是1008.4.继续输入tasklist|findstr "1008",回车,查看是哪个进程或者程序占用了1008端口,结果是:svchost.e

windows和Linux下查看端口和占用进程

windows系统下 c:\>netstat -ano |findstr "80"查看是否有进程占用80端口 TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 2736 占用80端口的进程,进程号为2736 c:\>tasklist |findstr "2736" peer.exe 2016 Console 0 16,064 K 查看占用该进程的程序为peer.exe c:\>taskkill /pid 2736 /F 终止pi

win7查看某个端口被占用的解决方法

1.开始---->运行---->cmd,或者是window+R组合键,调出命令窗口. 2.输入命令:netstat -ano,列出所有端口的情况.在列表中我们观察被占用的端口,比如是49157,首先找到它. 3.查看被占用端口对应的PID,输入命令:netstat -aon|findstr "49157",回车,记下最后一位数字,即PID,这里是2720. 4.继续输入tasklist|findstr "2720",回车,查看是哪个进程或者程序占用了27