簡體   English   中英

IP組播+ UDP:我應該接收所有組的數據嗎?

[英]IP Multicast + UDP: Should I receive data for all groups?

UDP IP組播的正確行為是什么?

想象一下自己的情況:

  1. 我們嘗試通過UDP談IP協議。
  2. 我們打開具有特定端口的UDP套接字(例如60001)
  3. 然后,我們將套接字加入某個多播組(例如239.192.0.1)
  4. 我們用端口60002打開另一個UDP套接字
  5. 然后我們將套接字加入其他多播組(例如239.192.0.2)

在Windows中使用Winsock完成此操作時,只有在同時滿足以下兩個條件的情況下,每個套接字才變為數據:

  • UDP端口匹配
  • 和多播組匹配。

這是一些Delphi代碼:

procedure Connect();
var err: Integer;
    wData: WsaData;
    reuse: Integer;
begin
  FillChar(wData, SizeOf(wData), 0);
  err := WSAStartup(MAKEWORD(2, 2), wData);
  if err = SOCKET_ERROR then Exit;

  _fd := socket(AF_INET, SOCK_DGRAM, 0);
  if _fd = INVALID_SOCKET then Exit;

  reuse := 1;
  if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, Pointer(@reuse), SizeOf(reuse)) < 0) then Exit;

  FillChar(_addr, sizeof(_addr), 0);
  _addr.sin_family := AF_INET;
  if (_listeningInterface = '0.0.0.0') or not _isIpAddress(_listeningInterface) then
    _addr.sin_addr.s_addr := htonl(INADDR_ANY)
  else
    _addr.sin_addr.s_addr := inet_addr(PAnsiChar(_listeningInterface));
  _addr.sin_port := htons(_port);

  if (bind(_fd, _addr, sizeof(_addr)) < 0) then Exit;

  if _isMulticast() then begin
    _mreq.imr_multiaddr.s_addr := inet_addr(PAnsiChar(_multicastGroup));
    if (_listeningInterface = '0.0.0.0') or not _isIpAddress(_listeningInterface) then
      _mreq.imr_interface.s_addr := htonl(INADDR_ANY)
    else
      _mreq.imr_interface.s_addr := inet_addr(PAnsiChar(_listeningInterface));
    // Joinig multicast group here. Note the _fd variable usage here.
    if (setsockopt(_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, @_mreq, sizeof(_mreq)) < 0) then Exit;
  end;
end;

當我們嘗試從Keil庫中為微控制器執行此操作時,沒有像setsockopt這樣的功能。 igmp_join函數不接受套接字變量,而僅接受多播組。

結果,我們無法指定UDP端口和多播組的對應關系,並且每個UDP套接字都成為我們加入的所有組的數據。

正確的方法有以下兩種:Keil或Windows?

兩種行為都是正確的。

您在哪個套接字上接收到哪個UDP數據包超出了IPv4多播定義的范圍。

通常只違反了您只收到加入該群組的流量的期望。 而且,所有操作系統都以不同的方式實現此目標。 Linux和Windows的行為不同,並且微控制器中的小型IP堆棧通常具有更簡單的行為。

基線,最壞的情況是:您將在UDP套接字上收到隨機的UDP數據包,即使是加入的組也是如此 但這在實踐中通常並沒有那么糟糕。 只是考慮時的指導原則。 原因是:操作系統可能會延遲成員資格刪除。 本地路由器延遲成員資格下降。 本地路由器將包含錯誤。

無論如何,您都需要處理接收到意外的UDP數據包,因為網絡中的任何人都可以偽造UDP數據包並將其以別人的名字發送到您的套接字。 此外,其他任何人都可以偽造IGMP數據包並將其“加入您”加入任何多播組。

這意味着:在實踐中,您始終需要進行應用程序級過濾,並且靜默忽略意外的UDP數據包。 在大多數IP堆棧上,都有一個(非常重要的)選項來確定接收到的UDP數據包的目標地址 這對於將多個多播組的流量分離出來最有用。

並且由於您現在知道IP堆棧的行為,因此您可以例如節省一些內存,而僅使用單個UDP套接字來接收所有UDP通信,並在應用程序端對其進行多路分解。 當然,這還取決於您的應用程序。

但是,是的,我知道您對IP多播定義不足感到失望。 我和你在一起! :-)

暫無
暫無

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

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