簡體   English   中英

在 Windows 中使用 C++ 進行 UPnP 端口轉發

[英]UPnP port forwarding with C++ in Windows

我正在嘗試使用 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;
}

非常感謝。

抱歉,但您沒有明確接收到的 NULL 指針的位置。

如果 CoCreateInstance 返回 null,則表示相關類未在相關機器上使用 OLE/COM 注冊——Skype/eMule 的工作無關緊要,因為它們可能使用內置於應用程序中的庫,而不是 COM 對象。

您應該確保 COM 對象已在使用它的系統上注冊 - 在注冊表中搜索 UPnPNAT uuid。

如果您想讓應用程序在多個系統上工作,那么您應該考慮直接鏈接到 .lib,而不是使用 COM 連接到在使用時可能已在系統上注冊或未注冊的對象.

很可能您沒有打開網絡發現。

我也經歷過同樣的問題,同時連接到來賓或公共網絡,並做一些調試我已經發現了upnpnat.dll是不是在所有在運行時加載時get_StaticPortMappingCollection(..)被調用。 如果您連接到專用網絡,則可能由於安全限制而發生這種情況。 可以在控制面板 -> 網絡和共享中心 -> 更改高級共享設置中進行檢查。

控制面板屏幕截圖

在這種情況下需要打開網絡發現。 對於專用網絡,這無關緊要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM