카테고리 없음
[네트웍/인터넷] Network Adaptor 가 여러개인 경우의 IP 구하기
정보모음1
2023. 9. 8. 08:59
반응형
// I have need to access the IP address on Win95/WinNT
// where we have TCP/IP on the network card, and also
// on a dial-up connection.
//
// The NM* internet controls have a property 'LocalIP',
// but this returns the address of the NIC, not the dial-up.
//
// How do I get the other IP address, or better still, how
// would I loop through all adaptors ?
// 테스트 결과 Windows NT 에서만 정확히 작동했음(ws2_32.dll 의 버전은 4.00 이었음)
// Windows 95(ws2_32.dll 의 버전은 4.10.1656 이었음) 는 정확히 동작 안함
// longword 형이 없어서 longint 로 대체하여 컴파일 해보았음
unit NetCardsUnit;
interface
uses Windows, Classes, WinSock;
const
MAX_PROTOCOL_CHAIN = 7;
WSAPROTOCOL_LEN = 255;
SIO_GET_INTERFACE_LIST = IOC_OUT or
((longint(sizeOf(longint)) and IOCPARM_MASK) shl 16) or
(longint(byte('t')) shl 8) or 127;
type
PINTERFACE_INFO = ^TINTERFACE_INFO;
TINTERFACE_INFO = packed record
iiFlags: longint;
iiAddress: TSockAddrIn;
iiBroadcastAddress: TSockAddrIn;
iiNetmask: TSockAddrIn;
end;
TGroup = integer;
PGroup = ^TGroup;
LPWSAOVERLAPPED = POverlapped;
PWSAPROTOCOLCHAIN = ^TWSAPROTOCOLCHAIN;
TWSAPROTOCOLCHAIN = packed record
ChainLen: integer; { the length of the chain, }
{ length = 0 means layered protocol, }
{ length = 1 means base protocol,}
{ length > 1 means protocol chain}
ChainEntries : array[0..MAX_PROTOCOL_CHAIN-1] of Longword; { a list of dwCatalogEntryIds }
end;
PWSAPROTOCOL_INFOA = ^TWSAPROTOCOL_INFOA;
TWSAPROTOCOL_INFOA = packed record
dwServiceFlags1 : longword;
dwServiceFlags2 : longword;
dwServiceFlags3 : longword;
dwServiceFlags4 : longword;
dwProviderFlags : longword;
ProviderId : TGUID;
dwCatalogEntryId : longword;
ProtocolChain : TWSAPROTOCOLCHAIN;
iVersion : integer;
iAddressFamily : integer;
iMaxSockAddr : integer;
iMinSockAddr : integer;
iSocketType : integer;
iProtocol : integer;
iProtocolMaxOffset : integer;
iNetworkByteOrder : integer;
iSecurityScheme : integer;
dwMessageSize : longword;
dwProviderReserved : longword;
szProtocol : array [0..WSAPROTOCOL_LEN+1-1] of char;
end;
PWSAOVERLAPPED_COMPLETION_ROUTINE = procedure(dwError:longword;
cbTransferred:longword; lpOverlapped:LPWSAOVERLAPPED;
dwFlags:longword); stdcall;
function WSASocket(af:integer; atype:integer; protocol:integer;
lpProtocolInfo:PWSAPROTOCOL_INFOA; g:TGroup; dwFlags:longword):TSocket; stdcall;
function WSAIoctl(s:TSocket; dwIoControlCode:longword; lpvInBuffer:Pointer;
cbInBuffer:longword; lpvOutBuffer:Pointer; cbOutBuffer:longword;
lpcbBytesReturned:Plongword; lpOverlapped:LPWSAOVERLAPPED;
lpCompletionRoutine:PWSAOVERLAPPED_COMPLETION_ROUTINE):integer; stdcall;
type
TNetCardData = class
private
public
socket: TSocket;
numInterfaceCards: integer;
ipAddress: array [1..21] of string;
interfaceList: array [0..20] of TINTERFACE_INFO;
constructor Create;
function GetNumOfInterfaces: integer;virtual;
end;
implementation
const
winsocket = 'ws2_32.dll';
function WSASocket; external winsocket name 'WSASocketA';
function WSAIoctl; external winsocket name 'WSAIoctl';
constructor TNetCardData.Create;
var
wsadata: TWSAData;
err,i,reOrder: integer;
begin
numInterfaceCards:=-1;
try
err := WSAStartup($202,wsadata);
if (err = 0) then
begin
numInterfaceCards := GetNumOfInterfaces; // this really gets all of the data
if numInterfaceCards <> -1 then
begin
reOrder := 1;
for i := numInterfaceCards-1 downTo 1 do // I do not want the self address of 127.0.0.1
begin
ipAddress[reOrder] := inet_ntoa(TSockAddrIn(interfaceList[i-1].iiAddress).sin_Addr);
reOrder := succ(reOrder); // the cards are in the interfacelist high to low.
end; // I want the order to be low to high.
end;
numInterfaceCards := numInterfaceCards-1; // I do not want the self address of 127.0.0.1
end;
finally
WSACleanup;
end;
end;
function TNetCardData.GetNumOfInterfaces:integer;
var
err: integer;
nBytesReturned: longint;
begin
result := -1;
socket := WSASocket(AF_INET,SOCK_DGRAM,0,nil,0,0);
if socket = SOCKET_ERROR then
Exit;
err := WSAIoctl(socket, SIO_GET_INTERFACE_LIST, nil, 0,
@interfaceList, sizeOf(interfaceList), @nBytesReturned, nil, nil);
if err = 0 then
result := nBytesReturned div sizeOf(TINTERFACE_INFO);
closesocket(socket);
end;
end.
반응형