[Windows中使用C ++进行的UPnP端口转发

问题描述 投票:3回答:2

我正在尝试使用C ++ IUPnPNAT接口在Windows下的P2P应用程序中实现自动端口转发,而我不能使其仅因为它始终返回NULL对象而起作用。我不确定我的路由器是否支持UPnP,因为它在Web界面中未显示任何选项,但是如果我安装eMule或Skype,它们会立即打开端口并正常工作,因此问题必须出在我的代码或在Microsoft界面中。 eMule和Skype如何做到?没人可以帮我吗?

我粘贴了我的代码:

WORD abre_puerto() {
WORD puerto, i; 
wchar_t buf_port[12], puerto_s[6]; 
char nombre[256], ip[16]; 
wchar_t ipw[16], descripcion[100];
struct addrinfo *resultado = NULL; 
struct addrinfo *ptr = NULL; 
struct addrinfo hints; 
struct sockaddr_in *sockaddr_ipv4;
IUPnPNAT *nat; 
IStaticPortMappingCollection *coleccion; 
IStaticPortMapping *mapeado; 
BSTR protocolo, ipb;

swprintf(buf_port, sizeof(buf_port), L"%d", time(NULL));
swprintf(puerto_s, sizeof(puerto_s), L"151%c%c", buf_port[wcslen(buf_port) - 2], buf_port[wcslen(buf_port) - 1]);
puerto = _wtoi(puerto_s);

if(gethostname(nombre, sizeof(nombre)) == SOCKET_ERROR) {return 0;}
ZeroMemory(&hints, sizeof(hints)); 
hints.ai_family = AF_INET; 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_protocol = IPPROTO_TCP;
if(getaddrinfo(nombre, NULL, &hints, &resultado) != 0) {return 0;}

sockaddr_ipv4 = (struct sockaddr_in *)resultado->ai_addr;
strcpy(ip, inet_ntoa(sockaddr_ipv4->sin_addr));
MultiByteToWideChar(CP_UTF8, 0, ip, -1, ipw, sizeof(ipw));
ipb = SysAllocString(ipw);

nat = NULL; coleccion = NULL; mapeado = NULL;

if(CoInitialize(NULL) != S_OK) {return 0;}

if(CoCreateInstance(__uuidof(UPnPNAT), NULL, CLSCTX_ALL, __uuidof(IUPnPNAT), (void **)&nat) != S_OK) {return 0;}
else if(nat == NULL) {return 0;}

if(nat->get_StaticPortMappingCollection(&coleccion) != S_OK) {return 0;}
else if(coleccion == NULL) {return 0;} //fails here: coleccion is allways NULL!

protocolo = SysAllocString(L"TCP");
wcscpy(descripcion, TEXT("PROOF"));

for(i = 0; i < 250; i++) {
if(coleccion->get_Item(puerto, protocolo, &mapeado) != S_OK || mapeado == NULL) {break;}
puerto++; mapeado->Release(); mapeado = NULL;
}
if(i == 250) {return 0;}
if(coleccion->Add(puerto, protocolo, puerto, ipb, TRUE, descripcion, &mapeado) != S_OK) {return 0;}
else if(mapeado == NULL) {return 0;}
nat->Release(); coleccion->Release(); mapeado->Release();
CoUninitialize();

return puerto;
}

非常感谢。

c++ upnp
2个回答
1
投票

抱歉,您在接收到的NULL指针的位置上不是明确的。

如果CoCreateInstance返回null,则表明相关类未在OLE / COM的相关计算机上注册-Skype / eMule工作无关紧要,因为它们可能使用内置的库应用程序,而不是COM对象。

您应确保在使用COM对象的系统上注册了该对象-在注册表中搜索UPnPNAT uuid。

如果要使应用程序在多个系统上工作,则应考虑直接链接到.lib,而不是使用COM来连接对象,该对象可能在系统上已注册,也可能未在系统上注册。正在使用。


0
投票

很可能您没有打开网络发现。

我在连接到[[来宾或公共]]网络并进行一些调试时遇到了相同的问题,我发现up​​npnat.dll在调用get_StaticPortMappingCollection(..)时在运行时根本没有加载。如果您<>连接到私有网络,则可能由于安全限制而发生这种情况。可以在控制面板->网络和共享中心->更改高级共享设置中进行检查。 Control Panel screen shot在这种情况下,需要打开网络发现。对于

private

网络而言,无关紧要。

© www.soinside.com 2019 - 2024. All rights reserved.