Форум: "Сети";
Текущий архив: 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.48 MB
Время: 0.011 c