最近写了一个简单的http服务器,现在正卡在端口映射的问题上。
风行等很多软件都能实现在路由器上自动添加端口映射,好像是通过upnp实现的,用VB能不能做到这一点啊?
谢谢大家!

解决方案 »

  1.   

    需要路由器支持你telnet或者web访问,然后可以通过这些接口发送对应的映射端口命令等来实现主要还是要路由器支持各种命令操作,以及提供对应的通信方式让你的程序控制
      

  2.   

    谢谢oyljerry!
    如果是用telnet或web连接到路由器来设置端口映射,那么不同的路由器的操作方法肯定也是不尽相同的,也不好用VB来做。
    而通过upnp来实现自动端口映射应该比较简单,现在的电脑一般都是用XP系统的,路由器一般也都是支持upnp的,所以这种方法的通用性也还过得去。
    不过如何通过编程通过upnp来进行自动端口映射的资料比较少,VB的更是没有搜到,下面有一段不知道是啥语言写的代码(俺只懂VB其他一窍不通,~~!!),哪位朋友费下心给翻译成VB的啊?
    原文见:http://hi.baidu.com/widebright/blog/item/de6f96ee5de6a42d2cf5345d.html
    case IDC_START:
        {
         BSTR bstrTypeURI = NULL;
         bstrTypeURI =    SysAllocString(L"urn:schemas-upnp-org:device:InternetGatewayDevice:1");
         IUPnPDevice * internetGatewayDevice =NULL;
         if (FindUPnPDevice(bstrTypeURI,&internetGatewayDevice))
         {
          char devicename[256];
          if (GetDeviceFriendlyName(internetGatewayDevice,devicename))
          { 
           hwndTreeView = GetDlgItem(hDlg,IDC_TREE1);
           AddItemToTree(hwndTreeView, devicename, 1);
          }
          SysFreeString(bstrTypeURI);
          bstrTypeURI = SysAllocString(L"urn:schemas-upnp-org:device:WANDevice:1");
          IUPnPDevice * wanDevice =NULL;
          if (GetChildDevice(internetGatewayDevice ,bstrTypeURI ,&wanDevice))
          {
           if (GetDeviceFriendlyName(wanDevice,devicename))
           { 
            hwndTreeView = GetDlgItem(hDlg,IDC_TREE1);
            AddItemToTree(hwndTreeView, devicename, 2);
           } 
           SysFreeString(bstrTypeURI);
           bstrTypeURI = SysAllocString(L"urn:schemas-upnp-org:device:WANConnectionDevice:1");
           IUPnPDevice * wanConnectionDevice =NULL;
           if (GetChildDevice(wanDevice ,bstrTypeURI ,&wanConnectionDevice))
           {
            if (GetDeviceFriendlyName(wanConnectionDevice,devicename))
            { 
             hwndTreeView = GetDlgItem(hDlg,IDC_TREE1);
             AddItemToTree(hwndTreeView, devicename, 3);
            }        SysFreeString(bstrTypeURI);
            bstrTypeURI = SysAllocString(L"urn:schemas-upnp-org:service:WANIPConnection:1");
            IUPnPService * WANIPConnection =NULL;
            if (GetService(wanConnectionDevice ,bstrTypeURI ,&WANIPConnection))
            {         hwndTreeView = GetDlgItem(hDlg,IDC_TREE1);
             AddItemToTree(hwndTreeView, "WANIPConnection", 4);        }
            if (WANIPConnection)
            {   
                         
                                    char IPAddress[64];
             if (InvokeGetExternalIPAddress(WANIPConnection,IPAddress))
             {
                 hwndTreeView = GetDlgItem(hDlg,IDC_TREE1);
                                AddItemToTree(hwndTreeView, IPAddress, 4);
             }         hwndTreeView = GetDlgItem(hDlg,IDC_TREE1);
                           AddItemToTree(hwndTreeView, "RemoteHost,ExternalPort,PortMappingProtocol,InternalPort,InternalClient,PortMappingEnabled,PortMappingDescription,PortMappingLeaseDuration", 4);
                                    
                                    char PortMapping[256];
             int i =0;
                             while(InvokeGetGenericPortMappingEntry(WANIPConnection,i,PortMapping))
             {
                 hwndTreeView = GetDlgItem(hDlg,IDC_TREE1);
                                AddItemToTree(hwndTreeView, PortMapping, 4);
              i ++;
             }
             WANIPConnection->Release();
            }
            SysFreeString(bstrTypeURI);
            bstrTypeURI = SysAllocString(L"urn:schemas-upnp-org:service:WANPPPConnection:1");
            IUPnPService * WANPPPConnection =NULL;
            if (GetService(wanConnectionDevice ,bstrTypeURI ,&WANPPPConnection))
            {         hwndTreeView = GetDlgItem(hDlg,IDC_TREE1);
             AddItemToTree(hwndTreeView, "WANPPPConnection", 4);        }
            if (WANPPPConnection)
            {
             WANPPPConnection->Release();
            }
           }
           if (wanConnectionDevice)
           {
            wanConnectionDevice->Release();
           }      }
          if (wanDevice)
          {
           wanDevice->Release();
          }     }
         SysFreeString(bstrTypeURI);
         if (internetGatewayDevice)
         {
          internetGatewayDevice->Release();
         }
        }    break;
      

  3.   

    你这一段是VC的...
    主要使用 IUPnPService 这个Com接口,你可以找一下VB相关的...
      

  4.   

    没找到vb使用iupnpservice接口的资料,倒是找到一篇不错的介绍upnp的资料:
    http://blog.csdn.net/zfrong/archive/2008/11/15/3305738.aspx
    按照里面介绍的,我写了一段测试代码:
    Private Sub Command1_Click()
        Dim sPost As String
        sPost = "M-SEARCH * HTTP/1.1" & vbCrLf & _
                "HOST: 239.255.255.250:1900" & vbCrLf & _
                "MAN:" & Chr(34) & "ssdp:discover" & Chr(34) & vbCrLf & _
                "MX:3" & vbCrLf & _
                "ST: UPnP: rootdevice " & vbCrLf
        Winsock1.RemoteHost = "239.255.255.250"
        Winsock1.RemotePort = 1900
        Winsock1.Connect
        Do Until Winsock1.State = 7
            DoEvents
        Loop
        Winsock1.SendData sPost
    End SubPrivate Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
        Dim sResult As String
        Winsock1.GetData sResult
        Debug.Print sResult
    End Sub但是Winsock1根本连不上,我测试的电脑上连接了打开upnp的路由器,没开防火墙,谁知道这是什么原因啊?
      

  5.   

    我直接用IE打开http://192.168.1.1:1900/igd.xml可成功返回路由器信息的xml文件的。
    是不是239.255.255.250:1900这种多播地址不能用winsock控件这样来连接啊?
      

  6.   

    不好意思,犯了一个低级错误,连接239.255.255.250:1900应该用UDP方式而不是TCP,把代码改了一下:
    Private Sub Command1_Click()
        Winsock1.Protocol = sckUDPProtocol
        Winsock1.RemoteHost = "239.255.255.250"
        Winsock1.RemotePort = 1900
        Winsock1.Bind
    End SubPrivate Sub Command2_Click()
        Dim sPost As String
        sPost = "M-SEARCH * HTTP/1.1" & vbCrLf & _
                "HOST: 239.255.255.250:1900" & vbCrLf & _
                "MAN:" & Chr(34) & "ssdp:discover" & Chr(34) & vbCrLf & _
                "MX:3" & vbCrLf & _
                "ST: UPnP: rootdevice " & vbCrLf
        Winsock1.SendData sPost
    End SubPrivate Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
        Dim sResult As String
        Winsock1.GetData sResult
        Debug.Print sResult
    End Sub测试以上代码时,绑定端口和发送数据都不会出现错误,但是Winsock接收不到任何数据。
    我用Sniff抓了一下,发现路由器确实每隔若干秒钟就会向239.255.255.250:1900以UDP方式发送一次数据,如何用Winsock来获取这些数据呢?这应该是个很简单的问题,但是我对Winsock控件UDP方式的用法确实知道的太少,请大家帮帮忙!
      

  7.   

    你这里是http访问,可以用VB发送http请求..