M
Micro Whai
Unregistered / Unconfirmed
GUEST, unregistred user!
(唉,自己的基础还是不行)
最近想写个WinSock程序,得到本机的IP地址,不过不是简单的得到一个:因为我的机器上有双网卡,一个用交叉线接另一台电脑,另一个接ADSL猫,这样就会有三个IP地址了。但是在使用gethostbyname的时候遇到一个指针方面的问题:(下面的内容和注释,是我的理解,不是想“侮辱”大家的能力,写得乱七八糟,不知道大家看不看得懂。呵呵)
--------------------------------------------------------------------
按照微软对hostent结构的定义,其中的h_addr_list又是一个指向地址指针数组的指针,真正的地址数据,要根据这个地址指针数组再去找;而这个地址指针数组的结构,虽然我在MSDN中没有看到明确的说明,只是说了一句是以空字符结束、以网络地址字节顺序排列(A NULL-terminated list of addresses for the host. Addresses are returned in network byte order.)不过,从其他人的相关代码中得知,应该就是TInAddr类型的数组结构。找到的代码片断,基本上都是类似的:
type
TaPInAddr = array [0..10] of PInAddr;
PaPInAddr = ^TaPInAddr;
var
phe : PHostEnt;
pptr : PaPInAddr;
I : Integer;
……
begin
……
phe :=GetHostByName(XXX);
……
pptr := PaPInAddr(Phe^.h_addr_list);
I := 0;
while pptr^ <> nil do begin
result:=StrPas(inet_ntoa(pptr^^));
Inc(I);
end;
……
end;
从上述代码来看,要取得所有IP,要先定义一个指定长度的PInAddr指针类型数组及指向它的指针PaPInAddr(sigh,“指针的指针”,我的最怕),然后将hostent中的h_addr_list强制转换为PaPInAddr类型,接着就可以通过这个指针数组,一步一步得到各个IP。
但是,似乎有点不对劲:TaPInAddr数组是定长的,可是一台机器的IP地址却有可能无穷多个,虽然长度为10应该足够,但是总觉得有点不“正宗”。于是我把上面的代码改成下面的样子,不再定义指针数组,直接用指针强制转换和指针加1:
var
phe : PHostEnt;
pTest : PInAddr;
strIP : String;
begin
……
phe := gethostbyname(XXX);
……
pTest := PInAddr(phe^.h_addr_list^);
while pTest <> nil do begin
strIP := inet_ntoa(pTest^);
MessageBox(0, PChar(strIP), 'ip', MB_OK);
Inc(pTest);
end;
……
end;
我想,指针类型的字节长度应该都是一样,Inc(指针)对于指针类型来说,也应该能够正确地找到下一个地址位置。可就是这里出问题,用改写过的方法,循环开始的时候能够获得正确的IP地址,可就是不会得到 nil,结果就是死循环。
我就是搞不明白:为什么第一种方式用指针数组能够找到 nil 来结束循环,而用第二种方式应该来说在本质上是一样的啊?Inc(指针)有问题造成访问错误的内存?可是用指针数组的方式,如果本机只有三个IP,定义数组长度为20,也应该是造成错误访问啊?
有点晕……
方法1:
hostent.h_addr_list = PaPInAddr --> TaPInAddr: +----------+
| PInAddr 1| --> TInAddr 1
+----------+
| PInAddr 2| --> TInAddr 2
+----------+
| …… |
+----------+
方法2:
hostent.h_addr_list = --> PInAddr +---------+
| PInAddr | --> TInAddr 1
Inc(PInAddr) +---------+
| PInAddr | --> TInAddr 2
Inc(PInAddr) +---------+
| …… |
+---------+
这有区别吗?
最近想写个WinSock程序,得到本机的IP地址,不过不是简单的得到一个:因为我的机器上有双网卡,一个用交叉线接另一台电脑,另一个接ADSL猫,这样就会有三个IP地址了。但是在使用gethostbyname的时候遇到一个指针方面的问题:(下面的内容和注释,是我的理解,不是想“侮辱”大家的能力,写得乱七八糟,不知道大家看不看得懂。呵呵)
--------------------------------------------------------------------
按照微软对hostent结构的定义,其中的h_addr_list又是一个指向地址指针数组的指针,真正的地址数据,要根据这个地址指针数组再去找;而这个地址指针数组的结构,虽然我在MSDN中没有看到明确的说明,只是说了一句是以空字符结束、以网络地址字节顺序排列(A NULL-terminated list of addresses for the host. Addresses are returned in network byte order.)不过,从其他人的相关代码中得知,应该就是TInAddr类型的数组结构。找到的代码片断,基本上都是类似的:
type
TaPInAddr = array [0..10] of PInAddr;
PaPInAddr = ^TaPInAddr;
var
phe : PHostEnt;
pptr : PaPInAddr;
I : Integer;
……
begin
……
phe :=GetHostByName(XXX);
……
pptr := PaPInAddr(Phe^.h_addr_list);
I := 0;
while pptr^ <> nil do begin
result:=StrPas(inet_ntoa(pptr^^));
Inc(I);
end;
……
end;
从上述代码来看,要取得所有IP,要先定义一个指定长度的PInAddr指针类型数组及指向它的指针PaPInAddr(sigh,“指针的指针”,我的最怕),然后将hostent中的h_addr_list强制转换为PaPInAddr类型,接着就可以通过这个指针数组,一步一步得到各个IP。
但是,似乎有点不对劲:TaPInAddr数组是定长的,可是一台机器的IP地址却有可能无穷多个,虽然长度为10应该足够,但是总觉得有点不“正宗”。于是我把上面的代码改成下面的样子,不再定义指针数组,直接用指针强制转换和指针加1:
var
phe : PHostEnt;
pTest : PInAddr;
strIP : String;
begin
……
phe := gethostbyname(XXX);
……
pTest := PInAddr(phe^.h_addr_list^);
while pTest <> nil do begin
strIP := inet_ntoa(pTest^);
MessageBox(0, PChar(strIP), 'ip', MB_OK);
Inc(pTest);
end;
……
end;
我想,指针类型的字节长度应该都是一样,Inc(指针)对于指针类型来说,也应该能够正确地找到下一个地址位置。可就是这里出问题,用改写过的方法,循环开始的时候能够获得正确的IP地址,可就是不会得到 nil,结果就是死循环。
我就是搞不明白:为什么第一种方式用指针数组能够找到 nil 来结束循环,而用第二种方式应该来说在本质上是一样的啊?Inc(指针)有问题造成访问错误的内存?可是用指针数组的方式,如果本机只有三个IP,定义数组长度为20,也应该是造成错误访问啊?
有点晕……
方法1:
hostent.h_addr_list = PaPInAddr --> TaPInAddr: +----------+
| PInAddr 1| --> TInAddr 1
+----------+
| PInAddr 2| --> TInAddr 2
+----------+
| …… |
+----------+
方法2:
hostent.h_addr_list = --> PInAddr +---------+
| PInAddr | --> TInAddr 1
Inc(PInAddr) +---------+
| PInAddr | --> TInAddr 2
Inc(PInAddr) +---------+
| …… |
+---------+
这有区别吗?