2012-01-06 10 views
3

C++のIUPnPNATインターフェイスを使用して、WindowsでP2Pアプリケーションの自動ポート転送を実現しようとしています。私はルータが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; 
} 

はどうもありがとうございました。

答えて

1

謝罪しますが、受信したNULLポインタの場所は明示的ではありません。

CoCreateInstanceがnullを返す場合、問題のクラスがOLE/COMの関連マシンに登録されていないことを示します。Skype/eMuleの作業は無関係です。おそらく、 COMオブジェクトではなく、アプリケーションに組み込まれています。

COMオブジェクトが使用しているシステムに登録されていることを確認してください。レジストリでUPnPNAT uuidを検索してください。

アプリケーションが複数のシステムで動作するようにしたい場合は、.libに直接リンクし、COMを使用してシステムに登録されていないオブジェクトに接続しないでくださいそれは使用されています。

+0

UPnpフレームワークはWindows上でのオプションのインストールであるようです。そのため、テストしているシステムにUPnPフレームワークがインストールされていない可能性があります。 – Petesh

+0

申し訳ありません申し訳ありませんが、私はあなたのコードで残っているコメントを読んで私の質問で言及することを忘れていましたが、IUPnPNATインターフェイスのメソッドget_StaticPortMappingCollectionへの呼び出しで、NULLオブジェクトは "IStaticPortMappingCollection * coleccion "メソッドが失敗しない場合は、S_OKを返します。それは、常に空のオブジェクトだけです。 CoCreateInstanceはS_OKを返し、IUPnPNATインターフェイスを正しく埋めます。マシンはWindows 7を使用し、同じルータの同じボックスにeMuleが動作し、起動するたびにポートを開きます(おそらくMiniUPnPc libを使用していますか?)。 – alnog

+0

最後に、私はMiniUPnPcのlibを使用し、正常に動作します。 – alnog