Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.14.84] |
|
Сообщ.
#1
,
|
|
|
Добрый вечер!
Как можно узнать, что в результате рассылки UDP broadcast программа получила свое же сообщение ? Дело в том, что при рассылке всем рассылающий получает свое же сообщение в том числе. Можно генерировать некоторый случайный ключ при отправке, запоминать его, а при приеме - сравнивать с ним, если совпали, то получили свое же. Интересует кроме этого варианта. При приеме пакета UDP можно узнать адрес отправителя и сравнить свой адрес с ним, но дело в том, что чтобы узнать свой адрес, необходимо (если я правильно понял) перебирать сетевые адаптеры, т.к. их может быть несколько. Получается уже не очень просто. Опять-таки, как я понимаю, не перебирать их не получится, т.к. рассылающий не указывает, с какого адаптера делается broadcast-рассылка. Подскажите, пожалуйста, какой самый простой способ решить эту задачу ? |
Сообщ.
#2
,
|
|
|
Цитата Lun2 @ Дело в том, что при рассылке всем рассылающий получает свое же сообщение в том числе. Вот простейший бродкастер юдп на паскале 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 У мну ничего не прилетает при броадкасте Либо у тебя петля в сети, либо ты что-то либо делаешь не так. Показывай код. Прикреплённая картинка
|
Сообщ.
#3
,
|
|
|
Цитата Lun2 @ При приеме пакета UDP можно узнать адрес отправителя и сравнить свой адрес с ним, но дело в том, что чтобы узнать свой адрес, необходимо (если я правильно понял) перебирать сетевые адаптеры, Lun2, приём UDP-пакета производится функцией "RecvFrom". ссылка В параметре "sockaddr *from" будет информация о компьютере ("IP" и "PORT") с которого прислан пакет. Используя эту информацию UDP-сервер отвечает на запросы UDP-клиентов. |
Сообщ.
#4
,
|
|
|
Gonarh, про петлю - честно говоря, не знаю как ее делать.
Сеть = роутер + 2 компа к нему, никаких доп. настроек. Broadcast - через sendto() на адрес "255.255.255.255". Почему я не должен получать свое ? Это же рассылка ВСЕМ, в числе которых и я Добавлено ЫукпШ, вопрос касался определение не отправившего, а того, что это мое же сообщение, т.е. я прислал сам себе через broadcast... Ну, насколько я понял, самое простое все же - включить в сообщение какой-то я отслеживать - если получил его, то значит от себя... |
Сообщ.
#5
,
|
|
|
Цитата Lun2 @ ЫукпШ, вопрос касался определение не отправившего, а того, что это мое же сообщение, т.е. я прислал сам себе через broadcast... Ещё разок: В результате работы RecvFrom будет получена структура sockaddr. Где будет информация, кто послал пакет. Просто попробуй посмотреть, что там. Какой там будет ip, например. --- Никто не запрещает посылать информацию самому себе. |
Сообщ.
#6
,
|
|
|
ЫукпШ все описал точно. В структуре sockaddr должен быть адрес самого себя
|
Сообщ.
#7
,
|
|
|
Цитата Lun2 @ Почему я не должен получать свое ? Потому что ты не знаешь как работает сетевое оборудование. Изучи как работают коммутаторы, фрейм с дст броадкаст улетит во все порты, кроме того откуда прилетел. Если нет петли, разумеется. Цитата Lun2 @ Это же рассылка ВСЕМ, в числе которых и я Нет, это рассылка всем, КРОМЕ тебя. Добавлено Цитата ЫукпШ @ Ещё разок: В результате работы RecvFrom будет получена структура sockaddr. Где будет информация, кто послал пакет. Просто попробуй посмотреть, что там. Какой там будет ip, например. Это не показатель, там м.б. src ip 0.0.0.0, тот же дхцп дисковер например. |