如何编程实现端口映射编程?(能在win2000或者winXP 下实现)   
  
哪位好心人给点源程序?   
  email:[email protected]

解决方案 »

  1.   

    http://topic.csdn.net/t/20021021/10/1111048.html
      

  2.   

    http://www.99inf.net/SoftwareDev/VC/37787.htm
      

  3.   

    http://www.maikr.com/kan.aspx?id=037bd800-b3df-4a72-b2b9-1bb1e737d1fe
      

  4.   

    我想通过UPNP的自动端口映射方式,不知道怎么实现,网上找了些资料说的也不清楚http://www.chq.name/content/view/318_49.html这里也讲不详细,汗
      

  5.   

    #include "stdafx.h"
    #include "upnp.h"#define UPNPPORTMAP0   _T("WANIPConnection")
    #define UPNPPORTMAP1   _T("WANPPPConnection")
    #define UPNPGETEXTERNALIP _T("GetExternalIPAddress"),_T("NewExternalIPAddress")
    #define UPNPADDPORTMAP _T("AddPortMapping")
    #define UPNPDELPORTMAP _T("DeletePortMapping")static const ulong UPNPADDR = 0xFAFFFFEF;
    static const int UPNPPORT = 1900;
    static const CString URNPREFIX = _T("urn:schemas-upnp-org:");bool MyUPnP::SetLocalIP(CString localIP)
    {//设置需要被映射局域网IP
    DWORD ip = inet_addr(localIP);

    if(IsLANIP(ip))
    {
    m_slocalIP = localIP;
    m_uLocalIP = ip;
    return true;
    }
    else
    {
    m_slocalIP.Empty();
    return false;
    }
    }
    //提供给外部的接口
    bool MyUPnP::AddPortMap(WORD internalPort ,CString protocol,CString description,WORD externalPort)
    {
    srand( (unsigned)time( NULL ) );
    if(m_slocalIP=="" || m_slocalIP.IsEmpty())
    {
    InitLocalIP();//自动获得本机的本地ip;
    }
    UPNPNAT_MAPPING m_maping;
    if(externalPort!=0)
    {
    m_maping.externalPort = externalPort;
    }
    else
    {
    srand( (unsigned)time( NULL ) );
    m_maping.externalPort = (WORD)( 2049 + (65535 - 2049) * rand() / (RAND_MAX + 1) );
    // m_maping.externalPort = (WORD)(2049+rand()%3000);
    }
    m_maping.internalPort = internalPort; if(protocol=="TCP")
    {
    m_maping.protocol= UNAT_TCP;
    }
    else
    if(protocol=="UDP")
    {
    m_maping.protocol= UNAT_UDP;
    }
    else
    {
    return false;
    }
    if(description!="")
    m_mapdescription =description;
    AddNATPortMapping(&m_maping);
    return true;

    }
    bool MyUPnP::DeletePortMap(WORD externalPort,WORD internalPort )
    {
    return true;
    }const CString getString(int i) //将整数转换成字符串型
    {
    CString s; s.Format(_T("%d"), i); return s;
    }const CString GetArgString(const CString& name, const CString& value)
    {
    return _T("<") + name + _T(">") + value + _T("</") + name + _T(">");
    }const CString GetArgString(const CString& name, int value)
    {
    return _T("<") + name + _T(">") + getString(value) + _T("</") + name + _T(">");
    }//SOAP是一种在分散,分布环境中用来交换结构化信息的轻量级协议。SOAP使用XML 技术来定义一个可扩展的消息框架,
    //这个消息框架提供了一个能在多种下层(underlying)协议上进行交换的消息构造。
    //框架被设计成独立于任何特定的编程模型和其他实现的具体语义。
    bool SOAP_action(CString addr, WORD port, const CString request, CString &response)//发送请求,并接收响应
    {
    //简单对象访问协议(SOAP)
    char buffer[10240]; const CString sa(request);
    int length = sa.GetLength();
    strcpy(buffer, (const char*)sa); DWORD ip = inet_addr(CString(addr));
    struct sockaddr_in sockaddr;
    memset(&sockaddr, 0, sizeof(sockaddr));
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(port);
    //sockaddr.sin_port = htons(1900);
    sockaddr.sin_addr.S_un.S_addr = ip;
    int s = socket(AF_INET, SOCK_STREAM, 0);
    u_long lv = 1; //设置为非阻塞模式
    ioctlsocket(s, FIONBIO, &lv);
    connect(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
    Sleep(20);
    int n = send(s, buffer, length, 0);//发送请求
    Sleep(100);
    int rlen = recv(s, buffer, sizeof(buffer), 0);//接收响应
    closesocket(s);
    if (rlen == SOCKET_ERROR) return false;
    if (!rlen) return false; response = CString(CString(buffer, rlen)); return true;
    }//发送请求
    //SSDP服务(用于寻找upnp设备)
    int SSDP_sendRequest(int s, DWORD ip, WORD port, const CString& request)
    {
    // AfxMessageBox(request);
    //简单服务发现协议(SSDP)
    char buffer[10240]; const CString sa(request);
    int length = sa.GetLength();
    strcpy(buffer, (const char*)sa); CString   strIP="239.255.255.250";   
    DWORD   dwIP;   
    dwIP   =   inet_addr(strIP); struct sockaddr_in sockaddr;
    memset(&sockaddr, 0, sizeof(sockaddr));
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(port);
    sockaddr.sin_addr.S_un.S_addr = dwIP; return sendto(s, buffer, length, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
    }//分析HTTP的响应
    bool parseHTTPResponse(const CString& response, CString& result)
    {
    int pos = 0;
    //CString status = response.Tokenize(_T("\r\n"), pos);
    int endpos=response.Find(_T("\r\n"),pos);
    CString status = response.Mid(pos,endpos-pos); result = response;
    result.Delete(0, endpos); pos = 0;
    endpos =status.Find(_T(" "), pos);
    pos= endpos+1;
    endpos = status.Find(_T(" "),pos);
    status = status.Mid(pos,endpos-pos);
    // status = status.Tokenize(_T(" "), pos);
    if (status.IsEmpty() || status[0]!='2') return false;
    return true;
    }//获得属性,获得<> 与</>标签间的内容
    const CString getProperty(const CString& all, const CString& name)
    {
    CString startTag = '<' + name + '>';
    CString endTag = _T("</") + name + '>';
    CString property; int posStart = all.Find(startTag);
    if (posStart<0) return CString(); int posEnd = all.Find(endTag, posStart);
    if (posStart>=posEnd) return CString(); return all.Mid(posStart + startTag.GetLength(), posEnd - posStart - startTag.GetLength());
    }MyUPnP::MyUPnP()
    : m_version(1)
    {
    WORD VersionRequested;
    WSADATA WsaData;
    VersionRequested=MAKEWORD(2,2);
    WSAStartup(VersionRequested,&WsaData); //启动WinSock2
    m_slocalIP="";
    m_uLocalIP = 0;
    m_mapdescription = "ItvSky";
    isSearched = false;}//将所有的端口映射移除
    MyUPnP::~MyUPnP()
    {
    UPNPNAT_MAPPING search;
    POSITION pos = m_Mappings.GetHeadPosition();
    while(pos){
    search = m_Mappings.GetNext(pos);
    RemoveNATPortMapping(search, false);
    } m_Mappings.RemoveAll();
    }
      

  6.   


    //内部搜索,向路由器发送HTTP请求,并分析得到的HTTP响应
    bool MyUPnP::InternalSearch(int version)
    {
    if(version<=0)version = 1;
    m_version = version;//#define UPNPPORTMAP0   _T("WANIPConnection")
    //#define UPNPPORTMAP1   _T("WANPPPConnection")
    //设备数
    #define NUMBEROFDEVICES 3
    CString devices[][2] = {
    {UPNPPORTMAP1, _T("service")},
    {UPNPPORTMAP0, _T("service")},
    {_T("InternetGatewayDevice"), _T("device")},
    }; SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
    sockaddr_in sa;
    sa.sin_family = AF_INET;
    //sa.sin_addr.s_addr = inet_addr(CT2CA(theApp.GetBindAddress()));
    sa.sin_addr.s_addr = INADDR_ANY;
    // sa.sin_addr.s_addr=inet_addr("192.168.1.125");
    sa.sin_port = htons(9990);
    if (s != INVALID_SOCKET)
    {
    int nRet = bind((SOCKET)s, (SOCKADDR*)&sa, sizeof(sa));
    if (nRet==SOCKET_ERROR) 

    closesocket(s); // ignore return value - error close anyway
    return false;

    }else
    return false;
    u_long lv = 1;
    //设置为非阻塞模式
    ioctlsocket(s, FIONBIO, &lv);
    //static const CString URNPREFIX = _T("urn:schemas-upnp-org:")

    /*
    urn:schemas-UPnP-org:service:serviceType:v 
    搜索同类服务.服务类型与版本由UPnP论坛工作委员会定义.
     */
    int rlen = 0;
    for (int i=0; rlen<=0 && i<500; i++) {
    if (!(i%100)) {
    for (int i=0; i<NUMBEROFDEVICES; i++) {
    m_name.Format(_T("%s%s:%s:%d"), URNPREFIX, devices[i][1], devices[i][0], version);
    CString request;
    request.Format(_T("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: %d\r\nST: %s\r\n\r\n"),
    6, m_name);
    int sendtoresult=SSDP_sendRequest(s, UPNPADDR, UPNPPORT, request);//向路由器发送HTTP请求
    }
    } Sleep(10);
    //3月12日加
    // CString m_request = _T("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 3\r\nST: UPnP:rootdevice\r\n\r\n");
    // SSDP_sendRequest(s,UPNPADDR,UPNPPORT,m_request);
    char buffer[10240];
    rlen = recv(s, buffer, sizeof(buffer), 0);//接收响应
    if (rlen <= 0) continue;
    closesocket(s); CString response = CString(CString(buffer, rlen));
    CString result;
    // AfxMessageBox(response);
    //分析从路由器来的HTTP响应
    if (!parseHTTPResponse(response, result)) return false; for (int d=0; d<NUMBEROFDEVICES; d++) {
    m_name.Format(_T("%s%s:%s:%d"), URNPREFIX, devices[d][1], devices[d][0], version);
    if (result.Find(m_name) >= 0) {
    for (int pos = 0;;) {
    int beginpos = result.Find(_T("LOCATION:"),pos);
    int endpos = result.Find(_T("\r\n"),beginpos);
    CString line = result.Mid(beginpos,endpos-beginpos);
    pos = endpos+1;
    // CString line = result.Tokenize(_T("\r\n"), pos);
    if (line.IsEmpty()) return false;
    CString name = line.Mid(0, 9);  //取前9个字符
    name.MakeUpper(); //转换成大写字母
    if (name == _T("LOCATION:")) {
    //LOCATION 包含根设备UPnP描述的URL地址
    line.Delete(0, 9);//删除前9个字符
    m_description = line;
    m_description.TrimLeft();
    return GetDescription();//获得属性
    }
    }
    }
    }
    }
    closesocket(s); return false;
    }bool MyUPnP::Search(int version)
    {
    // bool isComplete() const { return !m_controlurl.IsEmpty(); }
    if (isSearched) return isComplete(); isSearched = true; return InternalSearch(version);  //内部搜索,向路由器发送HTTP请求,并分析得到的HTTP响应,
    //并获得属性
    }//从m_description中获得端口和地址
    static CString NGetAddressFromUrl(const CString& str, CString& post, CString& host, int& port)
    {
    CString s = str; post = _T("");
    host = post;
    port = 0;
    int pos = s.Find(_T("://"));
    if (!pos) return CString();
    s.Delete(0, pos + 3);//把://删除掉了 pos = s.Find('/');//查找地址当中是否含有/
    if (!pos) {
    // 有/
    host = s;
    s = _T("");
    } else {
    //地址中没有/
    host = s.Mid(0, pos);
    s.Delete(0, pos);
    } if (s.IsEmpty()) {
    post = _T("");
    } else {
    post = s;
    } pos = 0;

    int endpos = host.Find(_T(":"),pos);
    CString addr= host.Mid(pos,endpos-pos);
    pos = endpos+1;
    endpos = host.Find(_T(":"),pos);
    s = host.Mid(pos,host.GetLength()-pos);
    //CString addr = host.Tokenize(_T(":"), pos);
    //s = host.Tokenize(_T(":"), pos);
    if (s.IsEmpty()) {
    port = 80;
    } else {
    port = atoi(s);
    } return addr;
    }
      

  7.   


    bool MyUPnP::GetDescription()
    {
    //bool Valid()const{return (!m_name.IsEmpty()&&!m_description.IsEmpty());}
    if(!Valid())return false;
    CString post, host, addr;
    int port = 0;
    //从m_description中获得端口和地址,并再返回给addr
    addr = NGetAddressFromUrl(m_description, post, host, port);
    if(addr.IsEmpty())return false;
    CString request = CString(_T("GET ")) + post + _T(" HTTP/1.1\r\nHOST: ") + host + _T("\r\nACCEPT-LANGUAGE: en\r\n\r\n");
    CString response;
    if (!SOAP_action(addr, port, request, response)) return false;
    CString result;
    if (!parseHTTPResponse(response, result)) return false; m_friendlyname = getProperty(result, _T("friendlyName"));
    m_modelname = getProperty(result, _T("modelName"));
    m_baseurl = getProperty(result, _T("URLBase"));
    if(m_baseurl.IsEmpty())m_baseurl = CString(_T("http://")) + host + _T("/");
    if(m_baseurl[m_baseurl.GetLength() - 1]!='/')m_baseurl += _T("/");

    CString serviceType = _T("<serviceType>") + m_name + _T("</serviceType>");
    int pos = result.Find(serviceType);
    if (pos >= 0) {
    result.Delete(0, pos + serviceType.GetLength());
    pos = result.Find(_T("</service>"));
    if (pos >= 0) {
    result = result.Mid(0, pos);
    m_controlurl = getProperty(result, _T("controlURL"));
    if (!m_controlurl.IsEmpty() && m_controlurl[0] == '/') {
    m_controlurl = m_baseurl + m_controlurl.Mid(1);
    }
    }
    } return isComplete();
    }//发送消息,并获得返回来获得属性
    CString MyUPnP::GetProperty(const CString& name, CString& response)
    {
    if (!isComplete())return CString();
    CString post, host, addr;
    int port = 0;
    addr = NGetAddressFromUrl(m_controlurl, post, host, port);
    if(addr.IsEmpty())return CString();
    CString cnt;
    CString psr;
    //Append附加
    cnt+=(_T("<s:Envelope\r\n    xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\r\n    "));
    cnt+=(_T("s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n  <s:Body>\r\n    <u:"));
    cnt+=(name);
    cnt+=(_T(" xmlns:u=\""));
    cnt+=(m_name);
    cnt+=(_T("\">\r\n    </u:"));
    cnt+=(name);
    cnt+=(_T(">\r\n  </s:Body>\r\n</s:Envelope>\r\n\r\n"));
    psr+=(_T("POST "));
    psr+=(post);
    psr+=(_T(" HTTP/1.1\r\nHOST: "));
    psr+=(host);
    psr+=(_T("\r\nContent-Length: "));
    psr+=(getString(CString(cnt).GetLength()));
    psr+=(_T("\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nSOAPAction: \""));
    psr+=(m_name);
    psr+=(_T("#"));
    psr+=(name);
    psr+=(_T("\"\r\n\r\n"));
    psr+=(cnt); CString request = psr;
    if (!SOAP_action(addr, port, request, response)) return CString();
    CString result;
    if (!parseHTTPResponse(response, result)) return CString(); return getProperty(result, response);
    }//调用命令,被deletePortmap和addPortmap调用
    bool MyUPnP::InvokeCommand(const CString& name, const CString& args)
    {
    if(!isComplete())return false;
    CString post, host, addr;
    int port = 0;
    addr = NGetAddressFromUrl(m_controlurl, post, host, port);
    if(addr.IsEmpty())return false;
    CString cnt;
    CString psr;
    cnt+=(_T("<?xml version=\"1.0\"?><s:Envelope\r\n    xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\r\n    "));
    cnt+=(_T("s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n  <s:Body>\r\n    <u:"));
    cnt+=(name);
    cnt+=(_T(" xmlns:u=\""));
    cnt+=(m_name);
    cnt+=(_T("\">\r\n"));
    cnt+=(args);
    cnt+=(_T("    </u:"));
    cnt+=(name);
    cnt+=(_T(">\r\n  </s:Body>\r\n</s:Envelope>\r\n\r\n"));
    psr+=(_T("POST "));
    psr+=(post);
    psr+=(_T(" HTTP/1.1\r\nHOST: "));
    psr+=(host);
    psr+=(_T("\r\nContent-Length: "));//Content-Length是这个XML文档的长度
    psr+=(getString(CString(cnt).GetLength()));
    psr+=(_T("\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nSOAPAction: \""));
    psr+=(m_name);
    psr+=(_T("#"));
    psr+=(name);
    psr+=(_T("\"\r\n\r\n"));
    psr+=(cnt); CString response;
    CString request = psr;
    if (!SOAP_action(addr, port, request, response)) return false;
    CString result;
    if (!parseHTTPResponse(response, result)) return false; return true;
    }
      

  8.   


    //添加端口映射
    bool MyUPnP::addPortmap(int eport, int iport, const CString& iclient, const CString& descri, const CString& type)
    {
    CString args; args.Empty();
    args+=(GetArgString(_T("NewRemoteHost"), _T("")));
    args+=(GetArgString(_T("NewExternalPort"), eport));//外部端口
    //GetArgString后,
    //变成<NewRxternalPort>eport</NexExternalPort>

    args+=(GetArgString(_T("NewProtocol"), type));//填TCP或UDP
    args+=(GetArgString(_T("NewInternalPort"), iport));//内部端口
    args+=(GetArgString(_T("NewInternalClient"), iclient));//一般就是本地IP地址
    args+=(GetArgString(_T("NewEnabled"), _T("1")));
    args+=(GetArgString(_T("NewPortMappingDescription"), descri));//填写端口映射的描述,
    //比如什么程序建立了这个端口 args+=(GetArgString(_T("NewLeaseDuration"), 0));//端口映射的时间,0表示不永久 return InvokeCommand(UPNPADDPORTMAP, args);
    }//删除一端口映射
    bool MyUPnP::deletePortmap(int eport, const CString& type)
    {
    CString args; args.Empty();
    args+=(GetArgString(_T("NewRemoteHost"), _T("")));
    args+=(GetArgString(_T("NewExternalPort"), eport));
    args+=(GetArgString(_T("NewProtocol"), type)); return InvokeCommand(UPNPDELPORTMAP, args);
    }/////////////////////////////////////////////////////////////////////////////////
    // Adds a NAT Port Mapping
    // Params:
    // UPNPNAT_MAPPING *mapping  ->  Port Mapping Data
    // If mapping->externalPort is 0, then
    // mapping->externalPort gets the value of mapping->internalPort
    // bool tryRandom:
    // If If mapping->externalPort is in use, tries to find a free
    // random external port.
    //
    // Return:
    // UNAT_OK:
    // Successfull.
    // UNAT_EXTERNAL_PORT_IN_USE:
    // Error, you are trying to add a port mapping with an external port
    // in use.
    // UNAT_NOT_IN_LAN:
    // Error, you aren't in a LAN -> no router or firewall
    // UNAT_ERROR:
    // Error, use GetLastError() to get an error description.
    /////////////////////////////////////////////////////////////////////////////////
    MyUPnP::UPNPNAT_RETURN MyUPnP::AddNATPortMapping(UPNPNAT_MAPPING *mapping, bool tryRandom)
    {
    CString ProtoStr, Proto; if(!IsLANIP(GetLocalIP())){
    SetLastError(_T("You aren't behind a Hardware Firewall or Router"));
    return UNAT_NOT_IN_LAN;
    }

    if (!isComplete()) {
    Search();
    if (!isComplete()) {
    SetLastError(_T("Can not found a UPnP Router"));
    return UNAT_ERROR;
    }
    } if (mapping->protocol == UNAT_TCP){
    Proto = _T("TCP");
    ProtoStr = _T("TCP");
    }
    else {
    Proto = _T("UDP");
    ProtoStr = _T("UDP");
    } if(mapping->externalPort == 0)
    mapping->externalPort = mapping->internalPort;// int retries = 255;
    WORD rndPort = mapping->externalPort;
    for (int retries = 255; retries; retries--) 
    {
    CString Desc;
    Desc.Format(_T("%s (%s) [%s: %u]"),m_mapdescription, mapping->description, ProtoStr, mapping->externalPort); if (addPortmap(mapping->externalPort, mapping->internalPort, GetLocalIPStr(), Desc, Proto)) {
    m_Mappings.AddTail(*mapping);
    return UNAT_OK;
    } if (!tryRandom) {
    SetLastError(_T("External NAT port in use"));
    return UNAT_EXTERNAL_PORT_IN_USE;
    }
    // srand( (unsigned)time( NULL ) );
    mapping->externalPort =(WORD)( 2049 + (65535 - 2049) * rand() / (RAND_MAX + 1) );
    } SetLastError(_T("External NAT port in use: Too many retries"));
    return UNAT_EXTERNAL_PORT_IN_USE;
    }/////////////////////////////////////////////////////////////////////////////////
    // Removes a NAT Port Mapping
    // Params:
    // UPNPNAT_MAPPING *mapping  ->  Port Mapping Data
    // Should be the same struct passed to AddNATPortMapping
    // bool removeFromList -> Remove the port mapping from the internal list
    // Should by allways true (dafault value if not passed).
    // If you set it to false can cause an unexpected error.
    //
    //
    // Return:
    // UNAT_OK:
    // Successfull.
    // UNAT_NOT_OWNED_PORTMAPPING:
    // Error, you are trying to remove a port mapping not owned by this class
    // UNAT_NOT_IN_LAN:
    // Error, you aren't in a LAN -> no router or firewall
    // UNAT_ERROR:
    // Error, use GetLastError() to get an error description.
    /////////////////////////////////////////////////////////////////////////////////
    MyUPnP::UPNPNAT_RETURN MyUPnP::RemoveNATPortMapping(UPNPNAT_MAPPING mapping, bool removeFromList)
    {
    if(!IsLANIP(GetLocalIP())){
    SetLastError(_T("You aren't behind a Hardware Firewall or Router"));
    return UNAT_NOT_IN_LAN;
    } if (!isComplete()) {
    Search();
    if (!isComplete()) {
    SetLastError(_T("Can not found a UPnP Router"));
    return UNAT_ERROR;
    }
    } for(POSITION pos = m_Mappings.GetHeadPosition(); pos!=NULL; m_Mappings.GetNext(pos)){
    UPNPNAT_MAPPING search = m_Mappings.GetAt(pos); if (search.externalPort == mapping.externalPort 
    && search.protocol == mapping.protocol)
    {
    CString Proto; if (mapping.protocol == UNAT_TCP)
    Proto = _T("TCP");
    else
    Proto = _T("UDP"); if (deletePortmap(mapping.externalPort, Proto)) {
    if(removeFromList)
    m_Mappings.RemoveAt(pos);
    return UNAT_OK;
    } else {
    SetLastError(_T("Error getting StaticPortMappingCollection"));
    return UNAT_ERROR;
    }
    }
    } SetLastError(_T("Port mapping not owned by this class"));
    return UNAT_NOT_OWNED_PORTMAPPING;
    }
      

  9.   


    //清除端口映射表
    void MyUPnP::clearNATPortMapping()
    {
    UPNPNAT_MAPPING search;
    POSITION pos = m_Mappings.GetHeadPosition();
    while(pos){
    search = m_Mappings.GetNext(pos);
    RemoveNATPortMapping(search, false);
    } m_Mappings.RemoveAll();
    }/////////////////////////////////////////////////////////////////////////////////
    // Initializes m_localIP variable, for future access to GetLocalIP()
    /////////////////////////////////////////////////////////////////////////////////
    //获得本地IP,被GetLocalIP和GetLocalIPStr调用
    void MyUPnP::InitLocalIP()
    {
    #ifndef _DEBUG
    try
    #endif
    {
    char szHost[256];
    if (gethostname(szHost, sizeof szHost) == 0){
    hostent* pHostEnt = gethostbyname(szHost);
    if (pHostEnt != NULL && pHostEnt->h_length == 4 && pHostEnt->h_addr_list[0] != NULL){
    UPNPNAT_MAPPING mapping;
    struct in_addr addr; memcpy(&addr, pHostEnt->h_addr_list[0], sizeof(struct in_addr));
    m_slocalIP = inet_ntoa(addr);
    m_uLocalIP = addr.S_un.S_addr;
    }
    else{
    m_slocalIP = _T("");
    m_uLocalIP = 0;
    }
    }
    else{
    m_slocalIP = _T("");
    m_uLocalIP = 0;
    }
    }
    #ifndef _DEBUG
    catch(...){
    m_slocalIP = _T("");
    m_uLocalIP = 0;
    }
    #endif
    }/////////////////////////////////////////////////////////////////////////////////
    // Returns the Local IP
    /////////////////////////////////////////////////////////////////////////////////
    //返回本地IP,以WORD的值返回
    WORD MyUPnP::GetLocalIP()
    {
    if(m_uLocalIP == 0)
    InitLocalIP();

    return m_uLocalIP;
    }/////////////////////////////////////////////////////////////////////////////////
    // Returns a CString with the local IP in format xxx.xxx.xxx.xxx
    /////////////////////////////////////////////////////////////////////////////////
    //以XXX.XXX.XXX.XXX的方式返回本地IP
    CString MyUPnP::GetLocalIPStr()
    {
    if(m_slocalIP.IsEmpty())
    InitLocalIP();

    return m_slocalIP;
    }/////////////////////////////////////////////////////////////////////////////////
    // Sets the value of m_lastError (last error description)
    /////////////////////////////////////////////////////////////////////////////////
    void MyUPnP::SetLastError(CString error) {
    m_slastError = error;
    };/////////////////////////////////////////////////////////////////////////////////
    // Returns the last error description in a CString
    /////////////////////////////////////////////////////////////////////////////////
    CString MyUPnP::GetLastError()

    return m_slastError; 
    }/////////////////////////////////////////////////////////////////////////////////
    // Returns true if nIP is a LAN ip, false otherwise
    /////////////////////////////////////////////////////////////////////////////////
    //判断IP是否是局域网的IP
    bool MyUPnP::IsLANIP(WORD nIP){
    // filter LAN IP's
    // -------------------------------------------
    // 0.*
    // 10.0.0.0 - 10.255.255.255  class A
    // 172.16.0.0 - 172.31.255.255  class B
    // 192.168.0.0 - 192.168.255.255 class C unsigned char nFirst = (unsigned char)nIP;
    unsigned char nSecond = (unsigned char)(nIP >> 8); if (nFirst==192 && nSecond==168) // check this 1st, because those LANs IPs are mostly spreaded
    return true; if (nFirst==172 && nSecond>=16 && nSecond<=31)
    return true; if (nFirst==0 || nFirst==10)
    return true; return false; 
    }
      

  10.   

    太感动了,白板兄,发一份到我邮箱(.h,.cpp和main测试部分)吧:[email protected]
    加奖:120分