3
我試圖在Windows下使用C++ IUPnPNAT接口實現P2P應用程序中的自動端口轉發,並且我無法僅僅因爲它返回一個NULL對象而使其工作。我不確定我的路由器是否支持UPnP,因爲它沒有在Web界面中顯示任何選項,但是如果我安裝eMule或Skype,它們立即打開端口並正常工作,所以問題必須出現在我的代碼中或在微軟的界面。 eMule和Skype如何做到這一點?一個人可以幫助我嗎?在Windows中使用C++進行UPnP端口轉發
我貼我的代碼:
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;
}
非常感謝你。
它看起來像UPnp框架是在Windows上的可選安裝 - 所以它可能只是沒有安裝在您正在測試的系統上。 – Petesh 2012-01-06 11:10:39
對不起,我忘了在我的問題中提到NULL對象,但是如果您閱讀我留在代碼中的註釋,它將調用IUPnPNAT接口的方法get_StaticPortMappingCollection,NULL對象是「IStaticPortMappingCollection * coleccion 「並且該方法不會失敗,返回S_OK,它只是全空的對象。 CoCreateInstance返回S_OK並正確填充IUPnPNAT接口。該機器使用Windows 7,並在同一個路由器的同一個盒子中,eMule每次啓動時都會運行並打開這些端口(可能使用MiniUPnPc庫?)。 – alnog 2012-01-06 12:27:47
最後我使用了MiniUPnPc lib並且工作正常。 – alnog 2012-01-21 18:04:41