首页 > 解决方案 > 如何使用 Windows API 'GetTcpTable' 找到可用的 tcp 端口?

问题描述

我正在尝试使用 windows api 'GetTcpTable',但我不知道如何准备数据结构 'PMIB_TCPTABLE' 并从中获取返回值。

PROCEDURE GetTcpTable EXTERNAL "Iphlpapi":U:
   DEFINE OUTPUT        PARAMETER mTcpTable              AS HANDLE TO MEMPTR. // the API expects a pointer, so use HANDLE TO syntax to pass one
   DEFINE INPUT-OUTPUT  PARAMETER SizePointer            AS HANDLE TO LONG.
   DEFINE INPUT         PARAMETER Order                  AS LONG.
   DEFINE RETURN        PARAMETER IPHLPAPI_DLL_LINKAGE   AS LONG.
END PROCEDURE.
 
DEFINE VARIABLE mTcpTable        AS MEMPTR   NO-UNDO.
DEFINE VARIABLE SizePointer      AS INT      NO-UNDO.
DEFINE VARIABLE Order            AS INT      NO-UNDO.
DEFINE VARIABLE IPHLPAPI         AS INT      NO-UNDO.
 
DEFINE VARIABLE mTempValue       AS MEMPTR   NO-UNDO.
DEFINE VARIABLE dwNumEntries     AS INT      NO-UNDO.
DEFINE VARIABLE dwState          AS INT      NO-UNDO.
DEFINE VARIABLE dwLocalAddr      AS INT64    NO-UNDO.
DEFINE VARIABLE dwLocalPort      AS INT      NO-UNDO.
DEFINE VARIABLE dwRemoteAddr     AS INT64    NO-UNDO.
DEFINE VARIABLE dwRemotePort     AS INT      NO-UNDO.
 
DEFINE VARIABLE ix     AS INTEGER NO-UNDO.
 
SizePointer = 4.
Order = 1.
SET-SIZE(mTcpTable) = SizePointer.
RUN GetTcpTable(OUTPUT mTcpTable, INPUT-OUTPUT SizePointer,INPUT Order, OUTPUT IPHLPAPI). //get ERROR_INSUFFICIENT_BUFFER and know the real buffer now
 
MESSAGE "IPHLPAPI is " IPHLPAPI SKIP // ERROR_INSUFFICIENT_BUFFER = 122
        "SizePointer is " SizePointer SKIP
   VIEW-AS ALERT-BOX.
 
SET-SIZE(mTcpTable) = 0.
SET-SIZE(mTcpTable) = SizePointer.
RUN GetTcpTable(OUTPUT mTcpTable, INPUT-OUTPUT SizePointer,INPUT Order, OUTPUT IPHLPAPI). 
 
MESSAGE "IPHLPAPI is " IPHLPAPI SKIP  // NO_ERROR = 0
        "SizePointer is " SizePointer SKIP
        GET-LONG(mTcpTable,1) SKIP //dwNumEntries
   VIEW-AS ALERT-BOX.
 
IF IPHLPAPI = 0 THEN DO:
   dwNumEntries = GET-LONG(mTcpTable,1).
 
   OUTPUT TO VALUE ("C:\temp\debug.txt") UNBUFFERED.
   DO ix = 0 TO dwNumEntries - 1.
      dwState                 = GET-UNSIGNED-LONG(mTcpTable,5 + ix * 20). // get value of dwState
      dwLocalAddr             = GET-UNSIGNED-LONG(mTcpTable,9 + ix * 20). // get value of dwLocalAddr
 
      SET-SIZE(mTempValue)    = 2.
      PUT-BYTE(mTempValue,2)  = GET-UNSIGNED-SHORT(mTcpTable,13 + ix * 20).
      PUT-BYTE(mTempValue,1)  = GET-UNSIGNED-SHORT(mTcpTable,14 + ix * 20).
      dwLocalPort             = GET-UNSIGNED-SHORT(mTempValue,1). // get value of dwLocalPort, The maximum size of an IP port number is 16 bits, so only the lower 16 bits should be used. The upper 16 bits may contain uninitialized data.
      SET-SIZE(mTempValue)    = 0.
 
      dwRemoteAddr            = GET-UNSIGNED-LONG(mTcpTable,17 + ix * 20). // get value of dwRemoteAddr
 
      SET-SIZE(mTempValue)    = 2.
      PUT-BYTE(mTempValue,2)  = GET-UNSIGNED-SHORT(mTcpTable,21 + ix * 20).
      PUT-BYTE(mTempValue,1)  = GET-UNSIGNED-SHORT(mTcpTable,22 + ix * 20).
      dwRemotePort            = GET-UNSIGNED-SHORT(mTempValue,1). // get value of dwRemotePort, The maximum size of an IP port number is 16 bits, so only the lower 16 bits should be used. The upper 16 bits may contain uninitialized data.
      SET-SIZE(mTempValue)    = 0.
 
      PUT UNFORMATTED dwState "~t" dwLocalAddr "~t" dwLocalPort "~t" dwRemoteAddr "~t" dwRemotePort "~r".
   END.
   OUTPUT CLOSE.
END.
 
SET-SIZE(mTcpTable) = 0.

我认为这个问题现在可以结束了:
https
://community.progress.com/s/feed/0D54Q000088eIeASAU?t=1602495359075&searchQuery 谢谢你们 :)

标签: openedgeprogress-4gl

解决方案


Microsoft 的文档通常具有结构的定义(请参阅https://docs.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcptable)。一旦你知道了这些 - 以及任何其他相关/指向/等 - 你可以使用MEMPTR数据类型和对它们进行操作的各种函数来创建和操作它们:SET-SIZE()GET-BYTES()并且GET-POINTER-VALUE()通常使用。在https://docs.progress.com/bundle/openedge-programmimg-interfaces/page/Shared-Library-and-DLL-Support.html上有关于此的文档。


推荐阅读