2011-03-04 16 views
3

私はUPnP AV/DLNA DMSを書いており、SSDPのメッセージを送受信する必要があります。 M-SEARCHパケットに応答して、INADDR_ANY0.0.0.0)にバインドすることを選択したリソース(この場合はHTTPサーバー)のURLを返信する必要があります。もちろん、このアドレスはM-SEARCHパケットの送信者にとって意味がありません。M-SEARCHが受信されたインターフェイスのアドレスが最も適切です。SSDPとインターフェイスのIPアドレス

返信パケットに送信する適切なアドレスを決定するにはどうすればよいですか?私はと考えられてきた

いくつかのアイデアがあります:

  1. は、各ソケットに別の受信機を結合します。受信者がM-SEARCHパケットを受け取ると、返信アドレスは返信でソケットのローカルアドレスを使用できます。しかし、これには、すべてのインターフェイスの把握と反復、およびインターフェイスの可用性の変化に応じて受信者の追加と削除が必要です。
  2. INADDR_ANYに1台の受信機を置き、interface netmasksを反復して、発生源を特定します。ただし、複数のインタフェースが同じサブネットを共有している可能性があります。
  3. 受信時にパケットのIPターゲットアドレスを抽出します。これはIP固有のものであり、ネットワーク抽象化のどこかで失われる可能性があります。

答えて

2

getsockname(2)次に、getnameinfo(3)は、TCP/IPスタックがソケットに割り当てたIPアドレスを報告します。 (明らかに、これはサーバとクライアントがNATシステムの反対側にある場合にクライアントが使用できるものとは一致しません;その場合、おそらくクライアントがサーバに接続するために使用できるIPアドレスを発見する巧妙なUPnPトリッキーがあります。)

私はあなたのサーバーは次のようになりますと仮定します。

lfd = socket(); 
ret = bind(lfd,...); 
connection = listen(lfd, 10); 
/* add connection to your select queue or poll queue */ 

あなたはこのようなコードを追加することができます:

struct sockaddr_storage me; 
socklen_t *len = sizeof(me); 
char name[40]; 
ret = getsockname(connection, &me, &len); 
ret = getnameinfo(&me, &len, name, sizeof(name), NULL, 0, NI_NUMERICHOST); 

getnameinfo(3)は、あなたのIPのためのstruct sockaddr_storagemeを検査住所。これらは汎用インターフェイスなので、IPv4またはIPv6アドレスで動作します。

+0

SSDPはUDPを超えています...あなたが言ったことは当てはまりますか? –

+1

@Matt Joiner:ああ、Wikipediaのページでたくさんの "HTTP"の言及が見られ、それがTCPであると仮定しました。 UDPソケットを接続し、接続されたソケットで 'getsockname(2)'を使うことができます。私は接続されていないソケットについてはほとんど分かりませんが、ソケットを接続するのは恐ろしいことではありません。 – sarnold

+0

これはうまくいくようです。私はUDPに焦点を当てるために質問を言い換えるべきです。 –