问题描述
我正在尝试使用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,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,21 + ix * 20).
PUT-BYTE(mTempValue,22 + ix * 20).
dwRemotePort = GET-UNSIGNED-SHORT(mTempValue,1). // get value of dwRemotePort,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.
- 是否有更好的方法来获取较低的16位?我不确定为什么需要将字节以相反的顺序放入mTempValue中,它是否与x86 PC的小字节序有关?
- 如果我在其他位计算机上运行代码,如何获得正确的起始位置以读取值
我认为问题可以立即解决:
https://community.progress.com/s/feed/0D54Q000088eIeASAU?t=1602495359075&searchQuery
谢谢大家:)
解决方法
Microsoft的文档通常具有结构的定义(请参见https://docs.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcptable)。一旦知道了这些以及与之相关/指向其他的其他信息,就可以使用MEMPTR
数据类型以及对其进行操作的各种功能来创建和操作它们:SET-SIZE()
,{{1}通常使用}和GET-BYTES()
。 https://docs.progress.com/bundle/openedge-programmimg-interfaces/page/Shared-Library-and-DLL-Support.html上有相关文档。