【发布时间】:2012-01-06 00:20:29
【问题描述】:
我正在尝试使用C++ IUPnPNAT接口在windows下的P2P应用程序中实现自动端口转发,但我不能让它工作,因为它总是返回一个NULL对象。我不确定我的路由器是否支持 UPnP,因为它在 Web 界面中没有显示任何选项,但是如果我安装 eMule 或 Skype,它们会立即打开端口并且工作正常,所以问题一定出在我的代码中或在微软界面中。 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;
}
非常感谢。
【问题讨论】: