На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > Broadcast рассылка через UDP - как узнать, что мы получили свое же сообщение
      Добрый вечер!
      Как можно узнать, что в результате рассылки UDP broadcast программа получила свое же сообщение ?

      Дело в том, что при рассылке всем рассылающий получает свое же сообщение в том числе.

      Можно генерировать некоторый случайный ключ при отправке, запоминать его, а при приеме - сравнивать с ним, если совпали, то получили свое же. Интересует кроме этого варианта.

      При приеме пакета UDP можно узнать адрес отправителя и сравнить свой адрес с ним, но дело в том, что чтобы узнать свой адрес, необходимо (если я правильно понял) перебирать сетевые адаптеры, т.к. их может быть несколько. Получается уже не очень просто.

      Опять-таки, как я понимаю, не перебирать их не получится, т.к. рассылающий не указывает, с какого адаптера делается broadcast-рассылка.

      Подскажите, пожалуйста, какой самый простой способ решить эту задачу ?
        Цитата Lun2 @
        Дело в том, что при рассылке всем рассылающий получает свое же сообщение в том числе.

        Вот простейший бродкастер юдп на паскале
        ExpandedWrap disabled
          unit Unit1;
           
          interface
           
          uses
            Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
            Dialogs, WinSock, StdCtrls;
           
          const
            WM_ASYNC = WM_USER + 1;
           
          type
            TForm1 = class(TForm)
              Button1: TButton;
              Button2: TButton;
              procedure Button1Click(Sender: TObject);
              procedure Button2Click(Sender: TObject);
            private
              { Private declarations }
            public
              FHandle: HWND;
              procedure SockWND(var AMsg: TMessage); message WM_ASYNC;
            end;
           
          var
            Form1: TForm1;
           
          implementation
           
          {$R *.dfm}
           
          procedure TForm1.Button1Click(Sender: TObject);
          var
            FWSAData: TWSAData;
            FSockAddr: TSockAddrIn;
            FSocket: HWND;
            Option: Boolean;
            Data: String;
          begin
            WSAStartup($0101, FWSAData);
            FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            with FSockAddr do begin
              sin_addr.S_addr := inet_addr('Х.Х.Х.166');
              Option := True;
              SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, PChar(@Option), SizeOf(Option));
              sin_port := htons(6767);
              sin_family := AF_INET;
            end;
            bind(FSocket, FSockAddr, SizeOf(FSockAddr));
            WSAAsyncSelect(FSocket, AllocateHWnd(SockWND), WM_ASYNC, FD_READ);
          end;
           
           
          procedure TForm1.SockWND(var AMsg: TMessage);
          var
              Buffer: array [0..8191] of Char;
              Size: Integer;
              SockAddr: TSockAddrIn;
          begin
              with AMsg do
                case Msg of
                    WM_ASYNC: begin
                        case WSAGetSelectEvent(LParam) of
                          FD_READ:
                          begin
                            FillChar(Buffer, 8192, #0);
                            Size := SizeOf(SockAddr);
                            recvfrom(WParam, Buffer[0], 8192, 0, SockAddr, Size);
                            Caption := StrPas(@Buffer);
                            DeallocateHWnd(FHandle);
                            closesocket(WParam);
                            WSACleanup;
                          end;
                    end;
                end
                  else DefWindowProc(FHandle, Msg, WParam, LParam);
                end;
          end;
           
          procedure TForm1.Button2Click(Sender: TObject);
          var
            FWSAData: TWSAData;
            FSockAddr: TSockAddrIn;
            FSocket: HWND;
            Option: Boolean;
            Data: String;
          begin
            WSAStartup($0101, FWSAData);
            FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            with FSockAddr do begin
              sin_addr.S_addr := INADDR_BROADCAST;
              Option := True;
              SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, PChar(@Option), SizeOf(Option));
              sin_port := htons(6767); // Это порт для броадкаста
              sin_family := AF_INET;
            end;
            Data := 'My first broadcast message!!!';
            SendTo(FSocket, Data[1], Length(Data), 0, FSockAddr, SizeOf(FSockAddr));
            closesocket(FSocket);
            WSACleanup;
          end;
           
          end.

        Батон1 - листит юдп порт 6767
        Батон2 - срёт броадкастом юдп на порт 6767
        У мну ничего не прилетает при броадкасте
        Либо у тебя петля в сети, либо ты что-то либо делаешь не так. Показывай код.
        Сообщение отредактировано: Gonarh -

        Прикреплённая картинка
        Прикреплённая картинка
          Цитата Lun2 @
          При приеме пакета UDP можно узнать адрес отправителя и сравнить свой адрес с ним, но дело в том, что чтобы узнать свой адрес, необходимо (если я правильно понял) перебирать сетевые адаптеры,

          Lun2, приём UDP-пакета производится функцией "RecvFrom".
          ссылка
          В параметре "sockaddr *from" будет информация о компьютере ("IP" и "PORT") с которого прислан пакет.
          Используя эту информацию UDP-сервер отвечает на запросы UDP-клиентов.
          Сообщение отредактировано: ЫукпШ -
            Gonarh, про петлю - честно говоря, не знаю как ее делать.
            Сеть = роутер + 2 компа к нему, никаких доп. настроек.
            Broadcast - через sendto() на адрес "255.255.255.255".
            Почему я не должен получать свое ?
            Это же рассылка ВСЕМ, в числе которых и я :)

            Добавлено
            ЫукпШ, вопрос касался определение не отправившего, а того, что это мое же сообщение, т.е. я прислал сам себе через broadcast...
            Ну, насколько я понял, самое простое все же - включить в сообщение какой-то я отслеживать - если получил его, то значит от себя...
              Цитата Lun2 @
              ЫукпШ, вопрос касался определение не отправившего, а того, что это мое же сообщение, т.е. я прислал сам себе через broadcast...

              Ещё разок:
              В результате работы RecvFrom будет получена структура sockaddr.
              Где будет информация, кто послал пакет.
              Просто попробуй посмотреть, что там.
              Какой там будет ip, например.
              ---
              Никто не запрещает посылать информацию самому себе.
              Сообщение отредактировано: ЫукпШ -
                ЫукпШ все описал точно. В структуре sockaddr должен быть адрес самого себя :yes:
                  Цитата Lun2 @
                  Почему я не должен получать свое ?

                  Потому что ты не знаешь как работает сетевое оборудование. Изучи как работают коммутаторы, фрейм с дст броадкаст улетит во все порты, кроме того откуда прилетел. Если нет петли, разумеется.
                  Цитата Lun2 @
                  Это же рассылка ВСЕМ, в числе которых и я :)

                  Нет, это рассылка всем, КРОМЕ тебя.
                  Добавлено
                  Цитата ЫукпШ @
                  Ещё разок:
                  В результате работы RecvFrom будет получена структура sockaddr.
                  Где будет информация, кто послал пакет.
                  Просто попробуй посмотреть, что там.
                  Какой там будет ip, например.

                  Это не показатель, там м.б. src ip 0.0.0.0, тот же дхцп дисковер например.
                  Сообщение отредактировано: Gonarh -
                  1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0393 ]   [ 17 queries used ]   [ Generated: 9.08.22, 16:51 GMT ]