计算机的本机真实IP地址和通用的127.0.0.1有何本质的区别?

lazydodo 2004-06-12 12:04:27
计算机的本机真实IP地址和通用的127.0.0.1有何本质的区别?

我在调试一个服务器软件的时候发现一个奇怪的现象。

这个服务器直接用winsock编写,服务器接受windows传入的网络事件,完成接收客户机指令并且向客户机传回指定文件的功能,为了调试方便,协议基本上沿用http的协议,也就是调试的时候客户机直接用IE代替,服务器相当于WWW服务器,准备调试好了再修改成一个专门的系统。

就是这样一个准www服务器,由于调试的时候服务器和IE是运行在同一台计算机上面的,于是发现在一些计算机上,如果用127.0.0.1访问服务器,服务器最多接受两个来自127.0.0.1的连接,第三个连接发出后服务器根本得不到windows传入的网络事件,当然也就不可能响应了。一旦原有的两个连接有一个结束了,第三个来自127.0.0.1的连接事件才会传入我的服务器(也就是说,前面windows好像冷藏了这些事件而不是丢失了这些事件)。

我以为我的软件有问题,于是在程序线程中加了很多延时,或者Application->ProcessMessages()。不过都没有解决问题。奇怪的是这个现象只在比较快的计算机上发生。
我在4台计算机上尝试运行,c2.4+winxp、c2.0+winxp、c2.0+winme都有这个问题,唯独一台p][+winxp的,无论有多少个来自127.0.0.1的网络事件都会准确无误的传入我的服务器软件。

不过,后来我发现,如果用本机真实IP地址来访问,上述计算机都没有问题.譬如本机分配ip为10.0.0.3,如果用http:\\10.0.0.3访问的话,我不用修改任何程序,这个程序都能够响应N多N多的连接请求。

虽然我的程序现在能够正常运行(我只是调试的时候才会用127.0.0.1,实际使用当然得用真实的ip了),不过这个现象产生的原因一直让我很好奇。

初步来看,我觉得和我的软件关系不大,应该属于系统软件的问题,因为我的软件根本没有收到来自windows系统的网络事件,这些事件好像滞留在windows内部了。于是我想了解一下,计算机的本机真实IP地址和通用的127.0.0.1有何本质的区别会导致这种现象?
...全文
1082 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
lazydodo 2004-06-13
  • 打赏
  • 举报
回复
====================================================================
我用BCB6写了个简化的测试模型:
FormActivate(TObject *Sender) 负责调入DLL,建立一个listen在端口80

MyOnNETEvent(TMessage &msg) 负责在Memo2中显示收到的网络事件并且响应这些事件。
简化起见,实际仅处理OnFD_ACCEPT和OnFD_READ,对于OnFD_ACCEPT将建立连接并且将sockID保存起来备用,对于OnFD_READ将读取数据随即丢弃之。


Timer1Timer(TObject *Sender)是一个定时器触发的函数,他将向每个TCP连接发送一个字节,从而达到数据回传状态的一个仿真。

界面上用Memo1\Memo2分别显示数据回传的情况和接收到的网络事件。
另外放置一个Label1和一个定时器。

============================H===================================
//---------------------------------------------------------------------------

#ifndef test3TCPH
#define test3TCPH
//---------------------------------------------------------------------------
#include <winsock2.h>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdTCPServer.hpp>
#define WM_SOCK WM_USER+100 //Sock消息
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMemo *Memo1;
TLabel *Label1;
TMemo *Memo2;
TTimer *Timer1;
void __fastcall FormActivate(TObject *Sender);
void __fastcall Timer1Timer(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
void __fastcall MyOnNETEvent(TMessage &msg);
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_SOCK,TMessage,MyOnNETEvent);
END_MESSAGE_MAP(TForm);
};

//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

============================CPP===================================

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "test3TCP.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void *WinHandle; //在win系统中,接受sock事件必须指定接受事件的窗口句柄
WSADATA WSAData;
//当前窗口是获得网络事件的接收者,因此要负责将事件传递给具体的通讯单元
int sockIDS[10];
int idcount=0;
void __fastcall OnFD_ACCEPT(int SockID) ///////如果有连接请求
{ //如果有TCP连接接入,
struct sockaddr_in sa;
int sa_len=sizeof(sa);
int my_sd=accept(SockID,(struct sockaddr far *)&sa,&sa_len); //接受之
WSAAsyncSelect(my_sd,WinHandle,WM_SOCK,FD_READ|FD_WRITE|FD_CLOSE);
sockIDS[idcount++]=my_sd; //并且纪录sockid供写出数据
}
void __fastcall OnFD_READ(int SockID) //////如果端口可以读取
{
char buf[2]; //如果有数据传入,接收
recv(SockID,buf,1,0);
buf[1]=0;
}
void __fastcall TForm1::MyOnNETEvent(TMessage &msg)
{
int my_sd,i;
my_sd=msg.WParam;
i=WSAGETSELECTEVENT(msg.LParam);
switch (i) {
case FD_ACCEPT:OnFD_ACCEPT(my_sd);break;
case FD_READ: OnFD_READ(my_sd); break;
}
if(Form1->Memo2->Lines->Count>1000) Form1->Memo2->Clear();
switch (i) {
case FD_ACCEPT:Form1->Memo2->Lines->Append("OnFD_ACCEPT "+String(my_sd)); break;
case FD_READ: Form1->Memo2->Lines->Append("OnFD_READ "+String(my_sd)); break;
case FD_WRITE: Form1->Memo2->Lines->Append("OnFD_WRITE "+String(my_sd)); break;
case FD_CLOSE: Form1->Memo2->Lines->Append("OnFD_CLOSE "+String(my_sd)); break;
}
// OnNETEvent(my_sd,i);
}
//---------------------------------------------------------------------------
int CreatListenPort(int port) ////////////////////创建监听端口
{
int ListenPortSock;
AnsiString ReportStr;ReportStr=DateTimeToStr(Now());
int r,fg;
fg=0;

ListenPortSock=socket(PF_INET,SOCK_STREAM,0);/* 建立套接字 【1、socket】*/
if (ListenPortSock < 0) {
fg=-1;
ReportStr=ReportStr+" Socket 建立失败";
goto qqq;
} //socket失败

struct sockaddr_in server; /* 指定连接套接字参数 【2、bind】 */
// struct hostent *hp;
server.sin_family = PF_INET;
server.sin_port = htons(port);
server.sin_addr.S_un.S_addr = INADDR_ANY;
r=bind(ListenPortSock,(struct sockaddr far *)&server,sizeof(server));
if (r<0) {
ReportStr=ReportStr+" bind() 指定连接套接字参数失败";
closesocket(ListenPortSock);/*释放端口*/
fg=-1;
goto qqq;
}

listen(ListenPortSock,1); //监听 //Set Event Function 【3、listen】

if(::WSAAsyncSelect(ListenPortSock,WinHandle,WM_SOCK,FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE)){//【4、WSAAsyncSelect】
ReportStr=ReportStr+" WSAAsyncSelect() 指定事件驱动机制失败";
closesocket(ListenPortSock);//释放端口
fg=-1;
goto qqq;
}
ReportStr=ReportStr+" Socket 建立成功 ["+String(ListenPortSock)+"]";
fg=ListenPortSock;
qqq:
return(fg);
}

void __fastcall TForm1::FormActivate(TObject *Sender)
{
WSAStartup((WORD)((1<<8)|1),(LPWSADATA)&WSAData); //打开WinSock DLL
WinHandle=Handle;
Label1->Caption="listen 80 SockID="+String(CreatListenPort(80));
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
int i;
char buf[10];
for (i=0;i<idcount;i++) {
buf[0]='A'+i;
buf[1]=0;
int ret;
ret = send(sockIDS[i],buf, 1, 0);//尝试输出这些有效数据
Memo1->Lines->Append(String(i));
}
}
//---------------------------------------------------------------------------



===================================================================
在测试计算机上开3个IE窗口,然后在每个IE的地址栏中输入127.0.0.1回车。
这样,前两个窗口都会在测试程序中看到连接的情况(当然IE自己啥也不会显示)
到了第3个窗口情况就有分化,还是仅仅前面叙述的那台P][计算机能够看到第三个
IE的接入情况,而在其它计算机上没有反应。在这个时候,如果在第三个IE中改输
入本机IP(10.0.0.3),所有计算机就都有反应了。



lazydodo 2004-06-13
  • 打赏
  • 举报
回复
点解可以打开无数多的http://127.0.0.1
但是恐怕保持连接状态的也就两个吧。
lazydodo 2004-06-12
  • 打赏
  • 举报
回复
杀毒软件
我在4台计算机上尝试运行,
c2.4+winxp(除了xp系统,啥都没有装,准确说,是一台dell的新裸机,装了xp就测试了)
c2.0+winxp(没有杀毒软件)
c2.0+winme(瑞星杀毒软件)
都有这个问题,
唯独一台p][+winxp(没有杀毒软件)
的,无论有多少个来自127.0.0.1的网络事件都会准确无误的传入我的服务器软件
============================================
另外,上述3台xp都是我用同一张光盘安装的。
waterflier 2004-06-12
  • 打赏
  • 举报
回复
你装了什么杀毒软件没有?
lazydodo 2004-06-12
  • 打赏
  • 举报
回复
呐为什么步骤少了反而消息停滞了
shenke410 2004-06-12
  • 打赏
  • 举报
回复
可乐说的很好,,127是本地的,不用经过线。
真实的要通过网络才行。。。。。。。
xcex 2004-06-12
  • 打赏
  • 举报
回复
127.0.0.1好象是环地址,好象是协议内规定,应该数据压根就没过线吧。
真实ip估计还是就应该网卡还是忙活了一阵?
Wenxy1 2004-06-12
  • 打赏
  • 举报
回复
偶没有深入这个问题,UP。
fish9flying 2004-06-12
  • 打赏
  • 举报
回复
回环地址,是本机用来测试的,不需要网络就可以直接用,真实的地址是用来和网络上的计算机通讯,实际上IP地址就向我们写信用的收信地址和发信地址一样,交换机通过你的IP地址和网络上的其他主机进行数据交换,它和网卡的48位地址有映射关系.
yhqs540 2004-06-12
  • 打赏
  • 举报
回复
127.0.0.1是loopback地址。这是一个网络接口,不同于一般用的接口。
实现方式是有所不同的
wangyangcheng 2004-06-12
  • 打赏
  • 举报
回复
可是如果对127.0.0.1有何限制的话,那我在同一台XP上面装有IIS和IE,点解可以打开无数多的http://127.0.0.1呢?
lazydodo 2004-06-12
  • 打赏
  • 举报
回复
环回地址不用经过网络传输,但是同一台机器环回地址之间的连接数有上限(2个)吗?

这恐怕要具体到操作系统了,而不是tcp/ip原理的问题我想。

还有奇怪的事,那台慢慢的p][没有问题,它也同样用的xp系统TCP连接啊。难道P][上的TCP和赛扬上的TCP遵循两种TCP标准?呵呵,我很迷惑... ...

我觉得“环回地址”不能够解释这个现象,要靠win系统如何具体实现了这个“环回地址”来解释了... ...
wqs_qiu_shi 2004-06-12
  • 打赏
  • 举报
回复
环回地址不用经过网络传输,
<<TCP/IP详解>>中有详细的介绍.

诊断是HCIE考试中重要的一板块,本课程围绕这一板块进行讲解,其中范文展示如下:                                    关于“AR29 loopback 0不能访问AR28 loopback0”的诊断报告一、故障根因。    经过分析,“AR29 loopback 0不能访问AR28 loopback0”的原因是,LSW6连接AR29和AR28的接口错误划分进不同的vlan,导致AR29和AR28不在一个广播域。 二、故障分析。    步骤2-1:故障现象重现,AR29使用loopback0作为源IP地址去ping AR28的loopback0,命令:   ping -a 10.5.1.29 10.5.1.28  PING 10.5.1.28: 56  data bytes, press CTRL_C to break    Request time out    Request time out    Request time out    Request time out    Request time out   --- 10.5.1.28 ping statistics ---    5 packet(s) transmitted    0 packet(s) received    100.00% packet loss      上面结果表明,确实存在故障,由于AR29和AR28之间运行OSPF协议,所以下一步将在AR29进一步查看路由表以确定是否存在AR28 loopback0接口的ip地址的路由信息。    步骤2-2:在AR29上检查路由表,以确定是否存在AR28 loopback0接口的ip地址的路由信息。查看命令及结果如下:    display ip routing-table Route Flags: R - relay, D - download to fib------------------------------------------------------------------------------Routing Tables: Public         Destinations : 12       Routes : 12        Destination/Mask    Proto   Pre  Cost      Flags NextHop         Interface       10.5.1.29/32  Direct  0    0           D   127.0.0.1       LoopBack0      10.5.1.33/32  OSPF    10   1           D   10.5.233.33     GigabitEthernet0/0/1     10.5.128.0/24  Direct  0    0           D   10.5.128.29     GigabitEthernet0/0/0    10.5.128.29/32  Direct  0    0           D   127.0.0.1       GigabitEthernet0/0/0   10.5.128.255/32  Direct  0    0           D   127.0.0.1       GigabitEthernet0/0/0     10.5.233.0/24  Direct  0    0           D   10.5.233.29     GigabitEthernet0/0/1    10.5.233.29/32  Direct  0    0           D   127.0.0.1       GigabitEthernet0/0/1   10.5.233.255/32  Direct  0    0           D   127.0.0.1       GigabitEthernet0/0/1      127.0.0.0/8   Direct  0    0           D   127.0.0.1       InLoopBack0      127.0.0.1/32  Direct  0    0           D   127.0.0.1       InLoopBack0127.255.255.255/32  Direct  0    0           D   127.0.0.1       InLoopBack0255.255.255.255/32  Direct  0    0           D   127.0.0.1       InLoopBack0     上面结果表明,AR29没有去往AR28 loopback0的路由。所以下一步将检查AR29和AR28的OSPF邻居关系。    步骤2-3:在AR29上检查AR29和AR28的OSPF邻居关系。检查命令及结果如下:    display ospf peer brief          OSPF Process 1 with Router ID 10.5.1.29              Peer Statistic Information    ----------------------------------------------------------------------------        Area Id          Interface                        Neighbor id      State        0.0.0.2          GigabitEthernet0/0/1             10.5.1.33        Full            ----------------------------------------------------------------------------        上面结果表明,AR29与AR28不存在OSPF邻居关系。所以初步判断OSPF配置错误,需要进一步检查确认。    步骤2-4:由于AR27与AR28 AR29处于同一OSPF区域中,所以可以通过AR27的测试结果来判断AR28配置是否正确,测试及结果如下:[AR27]display ospf peer brief                 //查看OSPF邻居                  OSPF Process 1 with Router ID 10.5.1.27                  Peer Statistic Information ---------------------------------------------------------------------------- Area Id          Interface                        Neighbor id      State     0.0.0.0          GigabitEthernet0/0/0             10.5.1.28        Full         ----------------------------------------------------------------------------[AR27]dis ip routing-table | in 10.5.1.28     //查看OSPF路由Route Flags: R - relay, D - download to fib------------------------------------------------------------------------------Routing Tables: Public         Destinations : 19       Routes : 19        Destination/Mask    Proto   Pre  Cost      Flags NextHop         Interface 10.5.1.28/32  OSPF    10   1           D   10.5.128.28     GigabitEthernet0/0/0 [AR27]    上面结果表明,AR27与AR28之间正常建立OSPF邻居,并且AR27能学习到AR28 loopback0的路由,说明AR28的OSPF配置正确,下一步将对比AR27与AR29的OSPF配置,来进一步判断AR29的OSPF配置是否正确。    步骤2-5:在AR27和AR29上使用命令display ospf brief检查对比AR29的OSPF配置是否正确,结果如下:[AR27]dis ospf brief        //查看AR27 OSPF协议简要信息         OSPF Process 1 with Router ID 10.5.1.27                 OSPF Protocol Information  RouterID: 10.5.1.27        Border Router:  ......(此处省略部分内容) Area: 0.0.0.0          (MPLS TE not enabled) Authtype: MD5   Area flag: Normal SPF scheduled Count: 15     ExChange/Loading Neighbors: 0 Router ID conflict state: Normal Area interface up count: 3.......

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧