![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
широковещательные сообщения [D5, Win2k]
борменталь © (2006-05-25 13:52:00)Здравствуйте!
В сетке используется чат. Легко пробивается с другие сегменты. Если открыть UDP-сокет, то его сообщения перехватываются. То есть (вероятно) используется UDP broadcast. Также сообщения ловятся приемником, забинденным на групповой multicast-адрес, то есть это не юникаст...
Пытаюсь сделать аналогично, но не получается. В пределах своего сегмента сообщения уходят и принимаются, за пределами сегмента - тишина. Пробовал и multicast, и broadcast - результат тот же :(
Но чат-то работает! (FChat, кстати).
посмотрите, пожалуйста, мой код - что я мог пропустить?
multicast:
var
h: TSocket;
MulticastTTL: DWORD;
multicastAddr: sockaddr_in;
sendString: array[0..512] of char;
multicastRequest: ip_mreq;
begin
MulticastTTL:= StrToInt(edit4.Text);
StrPCopy(sendString, Edit1.Text);
sendString[Length(edit1.text)]:= #0;
h:= socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if h<0 then DieWithError('socket');
// это я от бессилия... не помогло
// if setsockopt(h, IPPROTO_IP, IP_TTL, @multicastTTL,
// sizeof(MulticastTTL)) < 0 then
// DieWithError('setsockopt() failed');
if setsockopt(h, IPPROTO_IP, IP_MULTICAST_TTL, @multicastTTL,
sizeof(multicastTTL))<0 then DieWithError('TTL');
// вообще тоже не нужно. Но мешать не может (если тут нет ошибки)
FillChar(multicastAddr, sizeof(multicastAddr), 0);
multicastRequest.imr_multiaddr.s_addr := inet_addr(pchar(edit2.text));
multicastRequest.imr_interface.s_addr := htonl(INADDR_ANY);
if setsockopt(h, IPPROTO_IP, IP_ADD_MEMBERSHIP, @multicastRequest,
sizeof(multicastRequest)) < 0 then
DieWithError('setsockopt() failed');
getsockopt(h, IPPROTO_IP, IP_ADD_MEMBERSHIP, @multicastRequest,
sizeof(multicastRequest)) < 0 then
DieWithError('setsockopt() failed');
multicastAddr.sin_family:= AF_INET;
multicastAddr.sin_addr.S_addr:= inet_addr(pchar(edit2.text));
multicastAddr.sin_port:= htons(strtoint(edit3.text));
if sendto(h, sendString, StrLen(sendString)+1, 0, multicastAddr, sizeof(multicastAddr)) <> StrLen(sendString)+1 then
DieWithError('sendto() sent a different number of bytes than expected');
closesocket(h);
end;
код сервера (приемника)
var
MulticastTTL: DWORD;
multicastAddr: sockaddr_in;
multicastRequest: ip_mreq;
recvStringLen, xx: Integer;
recvString: array[0..512] of Char;
begin
MulticastTTL:= 128; // это не нужно, но мешать не должно
h:= socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if h<0 then DieWithError('socket');
FillChar(multicastAddr, sizeof(multicastAddr), 0);
multicastAddr.sin_family:= AF_INET;
multicastAddr.sin_addr.S_addr:= htonl(INADDR_ANY);
multicastAddr.sin_port:= htons(StrToInt(edit2.text));
// это не нужно, но мешать не должно
if setsockopt(h, IPPROTO_IP, IP_MULTICAST_TTL, @multicastTTL,
sizeof(multicastTTL))<0 then DieWithError('TTL');
if bind(h, multicastAddr, sizeof(multicastAddr)) < 0 then
DieWithError('bind() failed');
multicastRequest.imr_multiaddr.s_addr := inet_addr(pchar(edit1.text)); // групповой адрес
multicastRequest.imr_interface.s_addr := htonl(INADDR_ANY);
if setsockopt(h, IPPROTO_IP, IP_ADD_MEMBERSHIP, @multicastRequest,
sizeof(multicastRequest)) < 0 then
DieWithError('setsockopt() failed');
WSAAsyncSelect(h, Form1.Handle, WM_User, FD_Read);
затем в обработчике события FD_Read:
procedure TForm1.OnSocketRead(var M: TMessage);
var
MulticastTTL: byte;
multicastAddr: sockaddr_in;
multicastRequest: ip_mreq;
recvStringLen, xx: Integer;
recvString: array[0..512] of Char;
begin
FillChar(multicastAddr, sizeof(multicastAddr), 0);
recvStringLen:= SizeOf(multicastAddr);
xx := recvfrom(h, recvString, MAXRECVSTRING, 0, multicastAddr, recvStringLen);
if xx>0 then begin
recvString[xx] := #0;
Memo1.Lines.Add(recvString);
end;
end;
внутри сегмента все работает, так как я хочу.
UDP Broadcast:
приемник стандартный, ничего особенного. Можно пользоваться даже приемником из мультикаста.
клиент:
procedure TForm1.Button1Click(Sender: TObject);
var
h: TSocket;
MulticastTTL: DWORD;
Addr: sockaddr_in;
sendString: array[0..512] of char;
len: Integer;
yes: Integer;
begin
MulticastTTL:= 255; // пробовал и 5, и 64, и 128, и др. значения
sendString:= 'Cisco unified datagram report'#0;
h:= socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if h<0 then DieWithError('socket');
yes:= 1;
if setsockopt(h, SOL_SOCKET, SO_BROADCAST, @yes,
sizeof(yes)) < 0 then
DieWithError('setsockopt() failed');
if setsockopt(h, IPPROTO_IP, IP_TTL, @multicastTTL,
sizeof(MulticastTTL)) < 0 then
DieWithError('setsockopt() failed');
Addr.sin_family:= AF_INET;
Addr.sin_addr.S_addr:= inet_addr('255.255.255.255');
// Addr.sin_addr.S_addr:= inet_addr('10.255.255.255'); // как вариант
Addr.sin_port:= htons(9999); // на этом порту работает FChat
len:= sendto(h, sendString, StrLen(sendString)+1, 0, Addr, sizeof(Addr));
if len <> StrLen(sendString)+1 then
DieWithError('sendto() sent a different number of bytes than expected');
closesocket(h);
end;
В чем я неправ?
З.Ы. может ФЧат вообще на raw-сокетах работает? такое возможно? (сообщения приходят буквально на каждый хост)
Bormental (2006-05-25 17:38:00) [1]Isasa, ты спаситель, я уж уходить хотел. Проверю, сообщу результат.
isasa (2006-05-25 17:35:00) [2]Сорри, тоже погорячился.
myMulticast:=(myIP or (not myIPMask);
Bormental (2006-05-25 17:32:00) [3]Книжки читал. Потому и обращаюсь сюда. Говорю же, почему у меня не получается как у фчата? Код мой покритикуй, скажи чего в нем не хватает
isasa (2006-05-25 17:30:00) [4]Из-за чего ругань пошла!
myMulticast:=(myIP and myIPMask) and $FFFFFFFF;
255.255.255.255 это сильно круто. :)
Сергей М. (2006-05-25 16:04:00) [5]
> борменталь (25.05.06 15:37) [8]
> почему FChat сообщения передает?
По кочану.
FChat работает в пределах сегментов подсети твоего провайдера.
Иначе и быть не может, если провайдер при мозгах.
> умный нашелся
Дуй книжки читать.
борменталь (2006-05-25 15:37:00) [6]чорт... ты не задавался вопросом, почему FChat сообщения передает?
умный нашелся
Сергей М. (2006-05-25 15:33:00) [7]А ты не задавался ли себе вопросом, почему бродкаст-сообщение по адресу 255.255.255.255 не получает никто за пределами сети твоего провайдера ?
борменталь (2006-05-25 15:24:00) [8]как правильно осуществлять многоадресную передачу (multicast или broadcast) в многосегментных сетях?
только нужен код. Можно прокомментировать мой код, можно выложить чужой. Лишь бы разобраться, где я ошибся.
Сергей М. (2006-05-25 15:06:00) [9]В чем заключается "существо" ?
ТЗ - на всеобщее обозрение...
борменталь (2006-05-25 14:46:00) [10]
> Сергей М. © (25.05.06 14:37) [3]
> multicast имеет отношение к TCP, но не к UDP.
да мне все равно. Ты по существу скажи что-нибудь, пожалуйста!
Сергей М. (2006-05-25 14:37:00) [11]multicast имеет отношение к TCP, но не к UDP.
борменталь (2006-05-25 14:13:00) [12]а что не так?
сокет SOCK_DGRAM значит UDP.
но можно сказать и IP multicast, я не против
Сергей М. (2006-05-25 14:08:00) [13]Какой, нафих, в UDP "мультикаст" ?!