Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2003.09.18;
Скачать: [xml.tar.bz2];

Вниз

Сокеты. Широковещательный. Broadcast. Отправка данных   Найти похожие ветки 

 
Vorobyev Sergey   (2003-07-08 14:21) [0]

ВОПРОС: Как с помощью сокетов отправить широковещательное сообщение в сеть?

ПОЯСНЕНИЕ:
Есть приложения (допустим Reciever-ы), установленные на клиентских компьютерах в общей сети.. Допустим, каждый Receiver "слушает" определенный порт (с помощью TServerSocket)..
Как с помощью программы "отправителя информации" (Sender-а)отправить информацию всем запущенным приложениям Receiver-ам.. Причем естественно заранее неизвестно сколько и на каких машинах они запущены?


 
Digitman   (2003-07-08 14:41) [1]

TServerSocket/TClientSocket для этого не подходят - они используют протокол TCP, не позволяющий в общем случае реализовать настоящий бродкаст.

Пользуй протокол UDP и гнездовые компоненты, на нем базирующиеся. Sender при этом должен указать IP-адрес подсети твоего класса, младшие (в соответствии с маской подсети) октеты которого содержат $FF (255.). Receiver"ы должны принадлежать той же подсети и успешно выполнить бинд к одному и тому же порту, на который Sender будет посылать бродкаст.


 
Snap   (2003-07-10 20:57) [2]

>Digitman © (08.07.03 14:41)

в доках написано что если все 4 байта заполнить единичками, то тоже поканает как бродкаст. Просто не нужно будет выяснять, какого класса сеть, и вычислять сколко байт нужно заполнить. Хотя это не сложно конечно...


 
Nick2000   (2003-07-18 17:40) [3]

Не знаю, но может - так:
1. Проверить состояние порта.
2. слать пакет ему, если ресивер откликается - то получит, а нет...


 
Rouse_   (2003-07-19 01:21) [4]

Ну грубо говоря сделай так:

uses ..., Winsock;

procedure TForm1.FWButton1Click(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); // Это порт для броадкаста
( FSocket, Data[1], Length(Data)
Ну грубо говоря сделай так:

uses ..., Winsock;

procedure TForm1.FWButton1Click(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;


Как видишь - ничего сложного, только нужно бы проверять на ошибки (см. MSDN по используемым функциям), просто лениво было еще и обработчики в примере отстукивать...

Желаю успехов


 
Goblinus   (2003-07-19 02:11) [5]

Присоединяюсь к теме...

Как отправить широковещательный пакет, это понятно. А как его получить?

P.S. Вроде UDP не гарантирует доставку всех пакетов. И как быть в этом случае? Слать ответ на каждый пришедший пакет?

С уважением, Goblinus.


 
Rouse_   (2003-07-19 03:18) [6]

Ну Е!!!

public
FHandle: HWND;
procedure SockWND(var AMsg: TMessage); message WM_ASYNC;
end;

...

procedure TForm1.FWButton1Click(Sender: TObject);
var
FWSAData: TWSAData;
FSockAddr: TSockAddrIn;
FSocket: HWND;
Option: Boolean;
Data, SrvHost: String;
begin
WSAStartup($0101, FWSAData);
FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
with FSockAddr do
begin
SrvHost := "192.168.24.2"; // Это IP сервака
sin_addr.S_addr := inet_addr(PChar(SrvHost));;
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));
FHandle := AllocateHWnd(SockWND);
WSAAsyncSelect(FSocket, FHandle, 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], MAX_UDP_SIZE, 0, SockAddr, Size);
Caption := StrPas(@Buffer);
DeallocateHWnd(FHandle);
closesocket(WParam);
WSACleanup;
end;
end;
end
else
( FHandle, Msg, WParam, LParam)
Ну Е!!!

public
FHandle: HWND;
procedure SockWND(var AMsg: TMessage); message WM_ASYNC;
end;

...

procedure TForm1.FWButton1Click(Sender: TObject);
var
FWSAData: TWSAData;
FSockAddr: TSockAddrIn;
FSocket: HWND;
Option: Boolean;
Data, SrvHost: String;
begin
WSAStartup($0101, FWSAData);
FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
with FSockAddr do
begin
SrvHost := "192.168.24.2"; // Это IP сервака
sin_addr.S_addr := inet_addr(PChar(SrvHost));;
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));
FHandle := AllocateHWnd(SockWND);
WSAAsyncSelect(FSocket, FHandle, 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], MAX_UDP_SIZE, 0, SockAddr, Size);
Caption := StrPas(@Buffer);
DeallocateHWnd(FHandle);
closesocket(WParam);
WSACleanup;
end;
end;
end
else
DefWindowProc(FHandle, Msg, WParam, LParam);
end;
end;


Тоже проверок не вставлял. Все сделано очень грубо, но как пример работает.
Вообще-то нужно матчасть учить.

Желаю успехов


 
Goblinus   (2003-07-19 03:41) [7]


> Rouse_ © (19.07.03 03:18)


> SrvHost := "192.168.24.2"; // Это IP сервака

Спасибо большое за пример. А можно ли обойтись без сервера в данном случае (так, как это сделано в программах типа VyPress Chat и т.п.)? Спасибо.

С уважением,
Goblinus.


 
Rouse_   (2003-07-19 03:58) [8]

:))
Кто вам сказал что такие чаты не имеют сервера? Технология проста. Каждый чат и представляет собой сервер. Общаются они между собой именно через броадкаст датаграмы. А IP сервака - это IP адрес компьютера на котором запущен сервер. Так как каждый из чатов является сервером, значит данный IP должен быть локальным (но не 127.0.0.1) для каждого чата. В таком случае при броадкаст пакете, все чаты на всех компьютерах его получат и смогут обработать.

Понятно объяснено?

Желаю успехов.


 
Goblinus   (2003-07-19 11:59) [9]

Спасибо за объяснение. Остался лишь один вопрос: а разве все эти сервера сидят на одном порту? Как такое может быть? Разве при создании сокета с параметром SO_BROADCAST таких конфликтов не существует?

P.S. Sorry, просто недавно сетями заниматься начал - знать хочется ;)

С уважением,
Goblinus.


 
Rouse_   (2003-07-19 21:38) [10]

Естетсвенно они сидят на одном порту. Это возможно лишь потому - что находятся они на разных компьютерах. Если бы они находились на одном компьютере, то работал бы только один из них (самый первый запущенный), у остальных была бы ошибка при попытке выполнения bind(FSocket, FSockAddr, SizeOf(FSockAddr)); - "Can not bind socket. Address already in use."

Желаю успехов.


 
Goblinus   (2003-07-20 05:13) [11]

Спасибо большое за объяснение. Наконец-то я понял все, чего не понимал раньше, но очень хотел понять. Еще раз большое thanks, тема закрыта.

С уважением,
Goblinus.



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2003.09.18;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.011 c
4-58969
John_Russia
2003-07-16 17:38
2003.09.18
Медленно работает присвоение Parent у TWinControl


7-58924
Niko4543
2003-07-07 22:37
2003.09.18
AVP


1-58743
alextim
2003-09-06 18:29
2003.09.18
интерфейс как в outlook


14-58839
Jeer
2003-09-01 10:25
2003.09.18
Всех учащихся с новым учебным годом


14-58899
Е-Моё имя
2003-08-29 00:48
2003.09.18
День на форуме пропал не зря ;-))





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский