如题。局域网内互聊的可以实现了。
但不能像qq那样的,即通过路由器上网还是直连上网都能连通。
这两天搜了一下,有的说需要公网服务器什么的,有的说需要端口映射的不懂啊。谁能给个详细的解说吗?能给源码更好啊。ps:我有个小网站,有独立ip什么的。

解决方案 »

  1.   

    有网站有独立ip,暂时可先通过你服务器转发,服务器是服务端,其他都是客户端。客户端<----->服务器<---->客户端
      

  2.   


    能给出代码吗?大师。我才刚会局域网内用udp啊
      

  3.   


    不明白。。怎么在网页上运行服务端?什么定时签到?
    即使运行了服务端,并且服务器端可以得到发来的信息,但发出信息的时候怎么区分客户端?通过ip吗?客户端要是一样的ip呢?你们整的都太专业了,我才刚会复制别人的代码稍修改下粘贴给自己用
      

  4.   

    我有个想法,是通过写入数据库,然后根据用户名来判断信息的来源与去向。并用timer来实时检测数据库中是否有发给自己的信息。有的话就读过来。。但这样会不会太耗数据库了哈
      

  5.   

    这就是所谓的P2P技术,如果你了解Sock API的话,应该很好实现该技术,
    在网络上有很多 C 实现该技术的范例,在 Linux 论坛里这种已经被看为老掉牙的
    技术了,UDP、TCP的P2P代码满天飞,其实原理也很简单,用VB其实也可以实现,
    不过很少看见有VB这方面的代码亮相。我也写过这类程序,不过也是用VC,如果要用VB来写,感觉效率可能不行,因为
    虽然VB可以开多线程来处理过程,但要调到稳定还真是个费事的事情,还不如用VC
    来写还快一点。因为通常在VB中用Sock API来做网络通讯,都是用异步的方式处理
    过程,而这个“异步”,就是通过窗口消息来得到要处理的事件。这样一来,侦听
    和连接的东西多了,窗口也会创建得多了,感觉很怪,但用堵塞方式,如果不上线程,
    整个程序都动不了,更别说用了。其实原理很简单,首先需要在公网上有一台服务器,作用是提供用户信息和“打洞”
    用的。大致的服务器技术可以这样实现。
    公网服务器先创建一个 IP 协议的套接字,注意,是IP协议,不是TCP/IP或UDP/IP
    如:
    LocalSocketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);然后设置好基本的参数绑定套接字就可以开启线程狂读数据了,如:
    while(ServerObj->IsServer==TRUE){
       Sleep(1);
       rd = recvfrom(LocalHandle, (char *)&recvbuf, sizeof(stMessage), 0, (sockaddr *)&sender, &dwSender);
       if(rd<=0){
          // 错误
       }else{
          // 读到数据分析数据包和远程主机信息
          //.......
       }
    }运行过程是这样。
    服务器程序先启动,服务器程序在这称为 S
    然后启动客户端程序,客户端程序在这称为 C,若有多台客户端以 C1,C2,C3...Cn 作为区别
    C1 向服务器提交登录数据包(数据包格式可自己定义,
              如:
              0xB2     数据包头,固定为0xB2
              0x00000000     用户ID,登录时为0
              0x01     命令  1表示登录请求
                              2表示索取好友列表
                              3取得好友IP地址和端口
                              4打洞请求
              0x00     参数长度
              0x00,0x00...     参数(根据参数长度来定)
              0x000000    校验码,可以用CRC/CRC16/CRC32/异或 等校验方式校验数据的完整性
              0xB3     包尾,固定为0xB3
              )
    S 向 C1 返回登录成功结果数据包
    C1 向 S 发送索取好友列表请求
    S 判断用户已登陆后返回整个C1的好友列表给 C1
    C1 选择一个好友(称C2)弹出进行聊天,这时 CI 发送取得好友IP地址和端口命令给 S
    S 判断用户已登陆后返回C2记录在 S 上的最后一次 IP 记录给 C1
    C1 收到 S 发送过来的IP和端口后直接通过sendto发送给 C2
    C1 发送完成后等待 C2 的收到数据回应
    若C1判断回应超时,则发送一个打洞命令给 S
    然后C1 不断发送测试命令给 C2
    S 收到 C1 的打洞命令后,向 C2 发送包含 C1 的IP地址和端口信息的联通数据包
    C2 收到 S 的联通数据包请求后,C2 向 C1 发送测试请求
    这时因为 C1 不断重复的向 C2 一直在发送测试请求,只要 C2 同时也向 C1 发出信息,
    这样打洞过程就成功了。
    然后C1当收到C2的测试请求数据后,发送要发送的内容给 C2,
    C2就可以读到C1发过来的内容了以上是整个P2P基于IP包的形式的通讯过程。
    在VB里用控件我没实验过,不过VC中直接用Sock API测试成功,我两边的C端都是在内网
    通过路由上网的,运作很正常
      

  6.   

    等你客户端多了,网页应付不过来,再用专门的服务器,那就用12楼的技术好了。不过想用vb实现p2p穿透,提高一下是可以的,似乎网上有源码。
      

  7.   

    你这样还不如直接在IE上定时刷论坛里的某个帖子还简单点,全现成的,包括NT服务都不用考虑,呵呵。
    再懒一点的话,直接用QQ更简单。因为这种程序说白了开发已经没多大意义了,练手倒是不错。
      

  8.   

    我上面不是说了整个过程吗?只要你按照这种过程处理,肯定行的,
    如果要源码你才能开始动手,你可以到网上搜索一下呀,VC p2p源代码
    有了原理、操作过程、源代码你如果还弄不了,那就算别人教你也
    只是别人写一遍程序给你看而已。不会有太大区别。因为如果不能
    通过原理、操作过程、源代码这些资源自己弄懂,只能是基础差太
    远,即使别人教也不可能一步登天的取得成果。只有自己把基础打
    牢才是问题的解决方法。否则和直接用现成的工具没什么两样。
      

  9.   


    好人啊...不过你写那些我都看不懂..我也只是初学vb,不懂vc啊.
    "然后设置好基本的参数绑定套接字就可以开启线程狂读数据了"..看得我挺激动的就是不知道啥意思.顺便描述一下:这个功能是要嵌进公司一个软件中去的..并且这个软件其它功能已差不多ok了,就这个在线沟通的还没做出来.所以这个时候要换用vc来做会头大的.而我现在更想直接得到个代码,或者控件.我对vb了解本不多哈,更别说用vb来实现什么通信协议,等我学会了公司就要扣我money了.因为当时我试了局域网沟通很成功后对boss说了没问题的.
      

  10.   

    有.net源码,点击链接
      

  11.   

    不过你想要现成的接口,我记得好像是零几年的时候,深圳的一家公司
    出了一款P2P控件,支持多种语言调用,包括VB,不过要收点费用。好像
    也不是很贵,你应该能接受的,你可以搜索一下 P2P控件
      

  12.   

    这是一个P2P的VC范例代码,是个控制台程序。
    以下是服务器端的主要过程#pragma comment(lib, "ws2_32.lib")#include "windows.h"
    #include "..\proto.h"
    #include "..\Exception.h"UserList ClientList;void InitWinSock()
    {
    WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
    printf("Windows sockets 2.2 startup");
    throw Exception("");
    }
    else{
    printf("Using %s (Status: %s)\n",
    wsaData.szDescription, wsaData.szSystemStatus);
    printf("with API versions %d.%d to %d.%d\n\n",
    LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),
    LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));

    }
    }SOCKET mksock(int type)
    {
    SOCKET sock = socket(AF_INET, type, 0);
    if (sock < 0)
    {
            printf("create socket error");
    throw Exception("");
    }
    return sock;
    }stUserListNode GetUser(char *username)
    {
    for(UserList::iterator UserIterator=ClientList.begin();
    UserIterator!=ClientList.end();
    ++UserIterator)
    {
    if( strcmp( ((*UserIterator)->userName), username) == 0 )
    return *(*UserIterator);
    }
    throw Exception("not find this user");
    }int main(int argc, char* argv[])
    {
    try{
    InitWinSock();

    SOCKET PrimaryUDP;
    PrimaryUDP = mksock(SOCK_DGRAM); sockaddr_in local;
    local.sin_family=AF_INET;
    local.sin_port= htons(SERVER_PORT); 
    local.sin_addr.s_addr = htonl(INADDR_ANY);
    int nResult=bind(PrimaryUDP,(sockaddr*)&local,sizeof(sockaddr));
    if(nResult==SOCKET_ERROR)
    throw Exception("bind error"); sockaddr_in sender;
    stMessage recvbuf;
    memset(&recvbuf,0,sizeof(stMessage)); for(;;)
    {
    int dwSender = sizeof(sender);
    int ret = recvfrom(PrimaryUDP, (char *)&recvbuf, sizeof(stMessage), 0, (sockaddr *)&sender, &dwSender);
    if(ret <= 0)
    {
    printf("recv error");
    continue;
    }
    else
    {
    int messageType = recvbuf.iMessageType;
    switch(messageType){
    case LOGIN:
    {
    //  将这个用户的信息记录到用户列表中
    printf("has a user login : %s\n", recvbuf.message.loginmember.userName);
    stUserListNode *currentuser = new stUserListNode();
    strcpy(currentuser->userName, recvbuf.message.loginmember.userName);
    currentuser->ip = ntohl(sender.sin_addr.S_un.S_addr);
    currentuser->port = ntohs(sender.sin_port);

    ClientList.push_back(currentuser); // 发送已经登陆的客户信息
    int nodecount = (int)ClientList.size();
    sendto(PrimaryUDP, (const char*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));
    for(UserList::iterator UserIterator=ClientList.begin();
    UserIterator!=ClientList.end();
    ++UserIterator)
    {
    sendto(PrimaryUDP, (const char*)(*UserIterator), sizeof(stUserListNode), 0, (const sockaddr*)&sender, sizeof(sender)); 
    } break;
    }
    case LOGOUT:
    {
    // 将此客户信息删除
    printf("has a user logout : %s\n", recvbuf.message.logoutmember.userName);
    UserList::iterator removeiterator = NULL;
    for(UserList::iterator UserIterator=ClientList.begin();
    UserIterator!=ClientList.end();
    ++UserIterator)
    {
    if( strcmp( ((*UserIterator)->userName), recvbuf.message.logoutmember.userName) == 0 )
    {
    removeiterator = UserIterator;
    break;
    }
    }
    if(removeiterator != NULL)
    ClientList.remove(*removeiterator);
    break;
    }
    case P2PTRANS:
    {
    // 某个客户希望服务端向另外一个客户发送一个打洞消息
    printf("%s wants to p2p %s\n",inet_ntoa(sender.sin_addr),recvbuf.message.translatemessage.userName);
    stUserListNode node = GetUser(recvbuf.message.translatemessage.userName);
    sockaddr_in remote;
    remote.sin_family=AF_INET;
    remote.sin_port= htons(node.port); 
    remote.sin_addr.s_addr = htonl(node.ip); in_addr tmp;
    tmp.S_un.S_addr = htonl(node.ip);
    printf("the address is %s,and port is %d\n",inet_ntoa(tmp), node.port); stP2PMessage transMessage;
    transMessage.iMessageType = P2PSOMEONEWANTTOCALLYOU;
    transMessage.iStringLen = ntohl(sender.sin_addr.S_un.S_addr);
    transMessage.Port = ntohs(sender.sin_port);
                            
    sendto(PrimaryUDP,(const char*)&transMessage, sizeof(transMessage), 0, (const sockaddr *)&remote, sizeof(remote)); break;
    }

    case GETALLUSER:
    {
    int command = GETALLUSER;
    sendto(PrimaryUDP, (const char*)&command, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender)); int nodecount = (int)ClientList.size();
    sendto(PrimaryUDP, (const char*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender)); for(UserList::iterator UserIterator=ClientList.begin();
    UserIterator!=ClientList.end();
    ++UserIterator)
    {
    sendto(PrimaryUDP, (const char*)(*UserIterator), sizeof(stUserListNode), 0, (const sockaddr*)&sender, sizeof(sender)); 
    }
    break;
    }
    }
    }
    } }
    catch(Exception &e)
    {
    printf(e.GetMessage());
    return 1;
    } return 0;
    }
      

  13.   

    这是客户端的主要过程#pragma comment(lib,"ws2_32.lib")#include "windows.h"
    #include "..\proto.h"
    #include "..\Exception.h"
    #include <iostream>
    using namespace std;UserList ClientList;#define COMMANDMAXC 256
    #define MAXRETRY    5SOCKET PrimaryUDP;
    char UserName[10];
    char ServerIP[20];bool RecvedACK;void InitWinSock()
    {
    WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
    printf("Windows sockets 2.2 startup");
    throw Exception("");
    }
    else{
    printf("Using %s (Status: %s)\n",
    wsaData.szDescription, wsaData.szSystemStatus);
    printf("with API versions %d.%d to %d.%d\n\n",
    LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),
    LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
    }
    }SOCKET mksock(int type)
    {
    SOCKET sock = socket(AF_INET, type, 0);
    if (sock < 0)
    {
            printf("create socket error");
    throw Exception("");
    }
    return sock;
    }stUserListNode GetUser(char *username)
    {
    for(UserList::iterator UserIterator=ClientList.begin();
    UserIterator!=ClientList.end();
    ++UserIterator)
    {
    if( strcmp( ((*UserIterator)->userName), username) == 0 )
    return *(*UserIterator);
    }
    throw Exception("not find this user");
    }void BindSock(SOCKET sock)
    {
    sockaddr_in sin;
    sin.sin_addr.S_un.S_addr = INADDR_ANY;
    sin.sin_family = AF_INET;
    sin.sin_port = 0;

    if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0)
    throw Exception("bind error");
    }void ConnectToServer(SOCKET sock,char *username, char *serverip)
    {
    sockaddr_in remote;
    remote.sin_addr.S_un.S_addr = inet_addr(serverip);
    remote.sin_family = AF_INET;
    remote.sin_port = htons(SERVER_PORT);

    stMessage sendbuf;
    sendbuf.iMessageType = LOGIN;
    strncpy(sendbuf.message.loginmember.userName, username, 10); sendto(sock, (const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&remote,sizeof(remote)); int usercount;
    int fromlen = sizeof(remote);
    int iread = recvfrom(sock, (char *)&usercount, sizeof(int), 0, (sockaddr *)&remote, &fromlen);
    if(iread<=0)
    {
    throw Exception("Login error\n");
    } cout<<"Have "<<usercount<<" users logined server:"<<endl;
    for(int i = 0;i<usercount;i++)
    {
    stUserListNode *node = new stUserListNode;
    recvfrom(sock, (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&remote, &fromlen);
    ClientList.push_back(node);
    cout<<"Username:"<<node->userName<<endl;
    in_addr tmp;
    tmp.S_un.S_addr = htonl(node->ip);
    cout<<"UserIP:"<<inet_ntoa(tmp)<<endl;
    cout<<"UserPort:"<<node->port<<endl;
    cout<<""<<endl;
    }
    }void OutputUsage()
    {
    cout<<"You can input you command:\n"
    <<"Command Type:\"send\",\"exit\",\"getu\"\n"
    <<"Example : send Username Message\n"
    <<"          exit\n"
    <<"          getu\n"
    <<endl;
    }bool SendMessageTo(char *UserName, char *Message)
    {
    char realmessage[256];
    unsigned int UserIP;
    unsigned short UserPort;
    bool FindUser = false;
    for(UserList::iterator UserIterator=ClientList.begin();
    UserIterator!=ClientList.end();
    ++UserIterator)
    {
    if( strcmp( ((*UserIterator)->userName), UserName) == 0 )
    {
    UserIP = (*UserIterator)->ip;
    UserPort = (*UserIterator)->port;
    FindUser = true;
    }
    } if(!FindUser)
    return false; strcpy(realmessage, Message);
    for(int i=0;i<MAXRETRY;i++)
    {
    RecvedACK = false; sockaddr_in remote;
    remote.sin_addr.S_un.S_addr = htonl(UserIP);
    remote.sin_family = AF_INET;
    remote.sin_port = htons(UserPort);
    stP2PMessage MessageHead;
    MessageHead.iMessageType = P2PMESSAGE;
    MessageHead.iStringLen = (int)strlen(realmessage)+1;
    int isend = sendto(PrimaryUDP, (const char *)&MessageHead, sizeof(MessageHead), 0, (const sockaddr*)&remote, sizeof(remote));
    isend = sendto(PrimaryUDP, (const char *)&realmessage, MessageHead.iStringLen, 0, (const sockaddr*)&remote, sizeof(remote));

    for(int j=0;j<10;j++)
    {
    if(RecvedACK)
    return true;
    else
    Sleep(300);
    } sockaddr_in server;
    server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
    server.sin_family = AF_INET;
    server.sin_port = htons(SERVER_PORT);

    stMessage transMessage;
    transMessage.iMessageType = P2PTRANS;
    strcpy(transMessage.message.translatemessage.userName, UserName); sendto(PrimaryUDP, (const char*)&transMessage, sizeof(transMessage), 0, (const sockaddr*)&server, sizeof(server));
    Sleep(100);
    }
    return false;
    }void ParseCommand(char * CommandLine)
    {
    if(strlen(CommandLine)<4)
    return;
    char Command[10];
    strncpy(Command, CommandLine, 4);
    Command[4]='\0'; if(strcmp(Command,"exit")==0)
    {
    stMessage sendbuf;
    sendbuf.iMessageType = LOGOUT;
    strncpy(sendbuf.message.logoutmember.userName, UserName, 10);
    sockaddr_in server;
    server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
    server.sin_family = AF_INET;
    server.sin_port = htons(SERVER_PORT); sendto(PrimaryUDP,(const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr *)&server, sizeof(server));
    shutdown(PrimaryUDP, 2);
    closesocket(PrimaryUDP);
    exit(0);
    }
    else if(strcmp(Command,"send")==0)
    {
    char sendname[20];
    char message[COMMANDMAXC];
    int i;
    for(i=5;;i++)
    {
    if(CommandLine[i]!=' ')
    sendname[i-5]=CommandLine[i];
    else
    {
    sendname[i-5]='\0';
    break;
    }
    }
    strcpy(message, &(CommandLine[i+1]));
    if(SendMessageTo(sendname, message))
    printf("Send OK!\n");
    else 
    printf("Send Failure!\n");
    }
    else if(strcmp(Command,"getu")==0)
    {
    int command = GETALLUSER;
    sockaddr_in server;
    server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
    server.sin_family = AF_INET;
    server.sin_port = htons(SERVER_PORT); sendto(PrimaryUDP,(const char*)&command, sizeof(command), 0, (const sockaddr *)&server, sizeof(server));
    }
    }DWORD WINAPI RecvThreadProc(LPVOID lpParameter)
    {
    sockaddr_in remote;
    int sinlen = sizeof(remote);
    stP2PMessage recvbuf;
    for(;;)
    {
    int iread = recvfrom(PrimaryUDP, (char *)&recvbuf, sizeof(recvbuf), 0, (sockaddr *)&remote, &sinlen);
    if(iread<=0)
    {
    printf("recv error\n");
    continue;
    }
    switch(recvbuf.iMessageType)
    {
    case P2PMESSAGE:
    {
    char *comemessage= new char[recvbuf.iStringLen];
    int iread1 = recvfrom(PrimaryUDP, comemessage, 256, 0, (sockaddr *)&remote, &sinlen);
    comemessage[iread1-1] = '\0';
    if(iread1<=0)
    throw Exception("Recv Message Error\n");
    else
    {
    printf("Recv a Message:%s\n",comemessage);

    stP2PMessage sendbuf;
    sendbuf.iMessageType = P2PMESSAGEACK;
    sendto(PrimaryUDP, (const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&remote, sizeof(remote));
    } delete []comemessage;
    break; }
    case P2PSOMEONEWANTTOCALLYOU:
    {
    printf("Recv p2someonewanttocallyou data\n");
    sockaddr_in remote;
    remote.sin_addr.S_un.S_addr = htonl(recvbuf.iStringLen);
    remote.sin_family = AF_INET;
    remote.sin_port = htons(recvbuf.Port); stP2PMessage message;
    message.iMessageType = P2PTRASH;
    sendto(PrimaryUDP, (const char *)&message, sizeof(message), 0, (const sockaddr*)&remote, sizeof(remote));
                    
    break;
    }
    case P2PMESSAGEACK:
    {
    RecvedACK = true;
    break;
    }
    case P2PTRASH:
    {
    printf("Recv p2ptrash data\n");
    break;
    }
    case GETALLUSER:
    {
    int usercount;
    int fromlen = sizeof(remote);
    int iread = recvfrom(PrimaryUDP, (char *)&usercount, sizeof(int), 0, (sockaddr *)&remote, &fromlen);
    if(iread<=0)
    {
    throw Exception("Login error\n");
    }

    ClientList.clear(); cout<<"Have "<<usercount<<" users logined server:"<<endl;
    for(int i = 0;i<usercount;i++)
    {
    stUserListNode *node = new stUserListNode;
    recvfrom(PrimaryUDP, (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&remote, &fromlen);
    ClientList.push_back(node);
    cout<<"Username:"<<node->userName<<endl;
    in_addr tmp;
    tmp.S_un.S_addr = htonl(node->ip);
    cout<<"UserIP:"<<inet_ntoa(tmp)<<endl;
    cout<<"UserPort:"<<node->port<<endl;
    cout<<""<<endl;
    }
    break;
    }
    }
    }
    }
    int main(int argc, char* argv[])
    {
    try
    {
    InitWinSock();

    PrimaryUDP = mksock(SOCK_DGRAM);
    BindSock(PrimaryUDP); cout<<"Please input server ip:";
    cin>>ServerIP; cout<<"Please input your name:";
    cin>>UserName; ConnectToServer(PrimaryUDP, UserName, ServerIP); HANDLE threadhandle = CreateThread(NULL, 0, RecvThreadProc, NULL, NULL, NULL);
    CloseHandle(threadhandle);
    OutputUsage(); for(;;)
    {
    char Command[COMMANDMAXC];
    gets(Command);
    ParseCommand(Command);
    }
    }
    catch(Exception &e)
    {
    printf(e.GetMessage());
    return 1;
    }
    return 0;
    }
      

  14.   

    SupermanKing大哥的知识很强大,佩服一下下。
    看楼主的样子好像是要在企业即将使用的软件中添加一个聊天功能,当然有可能是异地有分公司的企业吧。
    我有一个小小的想法,没有时间认证的,哪位大哥证明一下?
    我个人感觉局域网和公网好像是一样的运行结构吧,如果A、B两台异地电脑相互通信,A、B两台都有公网IP,那么这两台电脑之间不是就好像局域网的两台电脑通讯了吗?这样A、B能不能直接通讯呢?
      

  15.   

    这个概念是错误的,因为Internet和内网架构是不一样的,先不说硬件层和硬件层间的通讯模式或
    交换机制,就由IP地址开始说起吧,IP地址现在通常使用的是4字节的IP地址,即最多支持256的4次方
    个地址,就是所最多支持40多亿个有用自己独立IP的终端在这个大网络环境运作,而世界人口总数在
    60多亿人口,单每人一个IP都分配不过来,何况还有无人看管的机房设备需要分配的IP,每个人可能
    拥有办公室、家庭、手机上网这类需求,而且介于分配管理上的需求,每个管理部门只有一定配额的
    IP段可分配,而还有可能因为地区,网络供应商和使用时间的问题浪费掉部分IP地址某些时段不在
    Internet上,所以,在Internet单靠真实的IP量是不能满足与目前的需求的,所以出现了伪IP的概念
    和IP6的概念,但IP6目前还没有很普及,我们通常也是在IP4的环境下上网,所以伪IP就和我们接触
    得比较多,只是很多人不知道而已。其实如果你注意一下会发现,每次用PPPOE拨号的时候,如果有心
    去某个网站看一下,会发现,网站上显示你的IP地址和你拨号显示的IP地址不一样,其实就是电信部门
    帮你分配了个伪IP,如果一样,恭喜你,你拥有了真实IP。
    伪IP其实是利用 TCP/IP 或 UDP/IP 通讯中的另一个参数配合实现的过程,这就是端口,通常一个内网
    在同一个路由环境下能运作是是在同一个网段下的,也就是所最多255个终端,而这255个终端只要配合
    路由协议中的端口,基本还是能满足常用的通讯需求的,因为基本上没人会用完所有的端口在一台终端
    机来跑,因为这么个弄法,可能没到路由交换层,你的终端机已经出问题了,呵呵。
    所以,Internet 的网络环境与内网环境是不一样的,当然,也有别的方法可以将网络环境设置得更为
    简单,就比如说VPN,当你连入Internet后,可以通过VPN拨号到你的VPN服务器,通过这个服务器将
    所有拨入VPN服务器的Internet终端模拟成一个局域网,这类似于驱动层的过滤驱动,他会把复杂的
    网络信息转换成内网方式进行通讯。这样一来,在程序设计上就简单很多。楼主也可以参考这种方式
    使用你的程序的,不用改动你原来的程序,只需要架设一台VPN服务器,然后在你的系统中建立个VPN
    拨号连接,每次都自动拨号就可以了。这些都是Windows Server 2003系统自带的设置。使用其实很
    简单的,你可以考虑考虑。
      

  16.   

    SupermanKing大哥非常热心!谢谢!