Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум на Исходниках.RU > C/C++: Сетевое программирование > Broadcast рассылка через UDP - как узнать, что мы получили свое же сообщение |
Автор: Lun2 25.07.22, 18:33 |
Добрый вечер! Как можно узнать, что в результате рассылки UDP broadcast программа получила свое же сообщение ? Дело в том, что при рассылке всем рассылающий получает свое же сообщение в том числе. Можно генерировать некоторый случайный ключ при отправке, запоминать его, а при приеме - сравнивать с ним, если совпали, то получили свое же. Интересует кроме этого варианта. При приеме пакета UDP можно узнать адрес отправителя и сравнить свой адрес с ним, но дело в том, что чтобы узнать свой адрес, необходимо (если я правильно понял) перебирать сетевые адаптеры, т.к. их может быть несколько. Получается уже не очень просто. Опять-таки, как я понимаю, не перебирать их не получится, т.к. рассылающий не указывает, с какого адаптера делается broadcast-рассылка. Подскажите, пожалуйста, какой самый простой способ решить эту задачу ? |
Автор: Gonarh 26.07.22, 05:15 |
Вот простейший бродкастер юдп на паскале <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> 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 У мну ничего не прилетает при броадкасте Либо у тебя петля в сети, либо ты что-то либо делаешь не так. Показывай код. |
Автор: ЫукпШ 26.07.22, 11:17 |
Цитата Lun2 @ При приеме пакета UDP можно узнать адрес отправителя и сравнить свой адрес с ним, но дело в том, что чтобы узнать свой адрес, необходимо (если я правильно понял) перебирать сетевые адаптеры, Lun2, приём UDP-пакета производится функцией "RecvFrom". ссылка В параметре "sockaddr *from" будет информация о компьютере ("IP" и "PORT") с которого прислан пакет. Используя эту информацию UDP-сервер отвечает на запросы UDP-клиентов. |
Автор: Lun2 27.07.22, 18:34 |
Gonarh, про петлю - честно говоря, не знаю как ее делать. Сеть = роутер + 2 компа к нему, никаких доп. настроек. Broadcast - через sendto() на адрес "255.255.255.255". Почему я не должен получать свое ? Это же рассылка ВСЕМ, в числе которых и я Добавлено ЫукпШ, вопрос касался определение не отправившего, а того, что это мое же сообщение, т.е. я прислал сам себе через broadcast... Ну, насколько я понял, самое простое все же - включить в сообщение какой-то я отслеживать - если получил его, то значит от себя... |
Автор: ЫукпШ 27.07.22, 18:48 |
Цитата Lun2 @ ЫукпШ, вопрос касался определение не отправившего, а того, что это мое же сообщение, т.е. я прислал сам себе через broadcast... Ещё разок: В результате работы RecvFrom будет получена структура sockaddr. Где будет информация, кто послал пакет. Просто попробуй посмотреть, что там. Какой там будет ip, например. --- Никто не запрещает посылать информацию самому себе. |
Автор: Oleg2004 27.07.22, 21:00 |
ЫукпШ все описал точно. В структуре sockaddr должен быть адрес самого себя |
Автор: Gonarh 29.07.22, 04:18 |
Потому что ты не знаешь как работает сетевое оборудование. Изучи как работают коммутаторы, фрейм с дст броадкаст улетит во все порты, кроме того откуда прилетел. Если нет петли, разумеется. Нет, это рассылка всем, КРОМЕ тебя. Добавлено Цитата ЫукпШ @ Ещё разок: В результате работы RecvFrom будет получена структура sockaddr. Где будет информация, кто послал пакет. Просто попробуй посмотреть, что там. Какой там будет ip, например. Это не показатель, там м.б. src ip 0.0.0.0, тот же дхцп дисковер например. |