如何接收局域网的广播信息(100分)

  • 主题发起人 主题发起人 YinZu
  • 开始时间 开始时间
Y

YinZu

Unregistered / Unconfirmed
GUEST, unregistred user!
服务器IP:129.9.1.100,子网隐码:255.255.255.0,端口:6008,
服务器向局域网内发送广播信信息,局域网内其他机器接收服务器发来的信息,
请问如何接收服务器发来的信息?用什么控件好,请给一个小例子,谢谢!
接收端的端口等如何设定?
 
UDP,例子,DELPHI自带。。
 
话题1125210的标题是: udp怎么实现局域网广播啊,请具体讲解! (50分)
分类:局域网 / 通讯 野兽王子 (2002-05-26 16:42:00)
udp怎么实现局域网广播啊,请具体讲解!

张无忌 (2002-05-26 16:44:00)
就是把UDP设成广播IP,一般是255.255.255.255
var
broadcast:bool;
broadcast:=true;
SetSockopt(FSocket,SOL_SOCKET,SO_BROADCAST, @broadcast,sizeof(broadcast));
就可以用sendto发广播了

野兽王子 (2002-05-26 16:46:00)
那用TNMUDP呢,也这样设吗?

张无忌 (2002-05-26 16:50:00)
用IDUDPSERVER把,他有广播的选项。

野兽王子 (2002-05-26 16:51:00)
我对这个都了解一些了啊,换别的不费劲吗

张无忌 (2002-05-26 16:54:00)
IDUDPSERVER不难用,而且有原代码,你多看看就应该会用,而且有例子的

野兽王子 (2002-05-26 16:55:00)
好的,先谢谢了,

胡柚 (2002-05-26 16:58:00)
IP地址四段中最后一段设定为255就可以了

野兽王子 (2002-05-26 17:01:00)
是这样吗?
hostname:='192.168.0.225';
nmudp1.ReportLevel :=status_basic;
nmudp1.RemoteHost:=HostName ;
nmudp1.LocalPort :=8888;
nmudp1.RemotePort :=8888;
就可以了吗?

张无忌 (2002-05-26 17:05:00)
一般是255.255.255.255,
[:)]

野兽王子 (2002-05-26 17:07:00)
哦,好的,,那其他的写的对吗?如果局域网没有机器运行这个程序,会不会出错呢?

crodling (2002-05-26 18:36:00)
你只管发送就可以了,没有机器运行这个程序也不会出错

zhukairu (2002-05-26 19:22:00)
我也想多了解用NMUDP如何广播的

chiefz318 (2002-05-28 0:36:00)
比如你的网段是192.168.0.X
你就往192.168.0.255发就可以了,你试试!

wind2000 (2002-05-28 1:48:00)
http://ph11.126.com->Delphi->编程技巧->....广播地址....(忘了,自已找)

zw84611 (2002-05-28 20:28:00)
广播有两种,一种是directed broadcast,如chiefz318所说:

比如你的网段是192.168.0.X
你就往192.168.0.255发就可以了

另一种是limited broadcast,如张无忌所说:

就是把UDP设成广播IP,一般是255.255.255.255
var
broadcast:bool;
broadcast:=true;
SetSockopt(FSocket,SOL_SOCKET,SO_BROADCAST, @broadcast,sizeof(broadcast));

两者都是可以的。
directed broadcast不需要SetSockopt(),以标准的C类网为例,直接发送x.x.x.255就可以了,
这种广播只有同一逻辑子网中的机器才能收到,也就是说对方地址应该是x.x.x.y,如果不是
即使在同一物理子网中也是收不到的。当然,这和子网掩码有关。

limited broadcast必须有SetSockopt(FSocket,SOL_SOCKET,SO_BROADCAST, @broadcast,sizeof(broadcast));
它的广播地址是255.255.255.255,它的好处是只要在同一子网中的主机,就可以收到这种
广播,而不必非要在统一逻辑子网中,例如,如果你的地址是x.x.x.1,那么这种广播,
地址是x.y.z.a的主机也能收到。

下面是用socket API实现limited broadcast的一个例子:
unit udp;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, winsock,
StdCtrls;

const
WM_SOCK = WM_USER + 1; //自定义windows消息
UDPPORT = 6543; //设定UDP端口号
//INADDR_ALLHOSTS_GROUP = u_long($e0000001); //D类地址224.0.0.1


(*
* Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
* Delphi5自带的winsock.pas中没有ip_mreq的定义。
*)

{type
ip_mreq = record
imr_multiaddr: in_addr; (* IP multicast address of group *)
imr_interface: in_addr; (* local IP address of interface *)
end;}

type
Tfrmmain = class(TForm)
Button1: TButton;
Edit1: TEdit;
Memo1: TMemo;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
s: TSocket;
addr: TSockAddr;
FSockAddrIn : TSockAddrIn;
//mreq:ip_mreq;
//利用消息实时获知UDP消息
procedure ReadData(var Message: TMessage); message WM_SOCK;
public
{ Public declarations }
procedure SendData(Content: String);
end;

var
frmmain: Tfrmmain;

implementation

{$R *.DFM}

procedure Tfrmmain.FormCreate(Sender: TObject);
var
TempWSAData: TWSAData;
optval: integer;
begin
// 初始化SOCKET
if WSAStartup($101, TempWSAData)=1 then
showmessage('StartUp Error!');

s := Socket(AF_INET, SOCK_DGRAM, 0);
if (s = INVALID_SOCKET) then //Socket创建失败
begin
showmessage(inttostr(WSAGetLastError())+' Socket创建失败');
CloseSocket(s);
//exit;
end;
//发送方SockAddr绑定
addr.sin_family := AF_INET;
addr.sin_addr.S_addr := INADDR_ANY;
addr.sin_port := htons(UDPPORT);
if Bind(s, addr, sizeof(addr)) <> 0 then
begin
showmessage('bind fail');
end;

optval:= 1;
if setsockopt(s,SOL_SOCKET,SO_BROADCAST,pchar(@optval),sizeof(optval)) = SOCKET_ERROR then
begin
showmessage('无法进行UDP广播');
end;

{mreq.imr_multiaddr.S_addr := INADDR_ALLHOSTS_GROUP;
mreq.imr_interface.S_addr := INADDR_ANY;
if setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,pchar(@mreq),sizeof(mreq)) = SOCKET_ERROR then
begin
showmessage('无法进行UDP组播');
end;}


WSAAsyncSelect(s, frmmain.Handle , WM_SOCK, FD_READ);
//接收端SockAddrIn设定
FSockAddrIn.SIn_Family := AF_INET;
FSockAddrIn.SIn_Port := htons(UDPPORT);

label3.Caption := '端口:'+inttostr(UDPPORT);
end;

procedure Tfrmmain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseSocket(s);
end;

procedure Tfrmmain.ReadData(var Message: TMessage);
var
buffer: Array [1..4096] of char;
len: integer;
flen: integer;
Event: word;
value: string;
begin
flen:=sizeof(FSockAddrIn);
FSockAddrIn.SIn_Port := htons(UDPPORT);
Event := WSAGetSelectEvent(Message.LParam);
if Event = FD_READ then
begin
len := recvfrom(s, buffer, sizeof(buffer), 0, FSockAddrIn, flen);
value := copy(buffer, 1, len);
Memo1.Lines.add(value)
end;
end;

procedure Tfrmmain.SendData(Content: String);
var
value{,hostname}: string;
len: integer;
begin
FSockAddrIn.SIn_Addr.S_addr := INADDR_BROADCAST;
//FSockAddrIn.SIn_Addr.S_addr := inet_addr(pchar(Edit1.text)); //INADDR_BROADCAST; //INADDR_BROADCAST = -1 ?
value := Content;
len := sendto(s, value[1], Length(value), 0, FSockAddrIn, sizeof(FSockAddrIn));
if (WSAGetLastError() <> WSAEWOULDBLOCK) and (WSAGetLastError() <> 0) then
showmessage(inttostr(WSAGetLastError()));
if len = SOCKET_ERROR then
showmessage('send fail');
if len <> Length(value) then
showmessage('Not Send all');
end;

procedure Tfrmmain.Button1Click(Sender: TObject);
begin
senddata(Edit2.text);
end;

end.



cook (2002-06-08 20:40:00)
广播地址是这样计算的
比如你的地址是123.123.123.123
如果子网掩码是255.255.255.0
那么广播地址是123.123.123.255
如果广播地址是255.255.0.0
那么广播地址是123.123.255.255
类推。。。
TNMUDP可以这样用



野兽王子 (2002-08-16 15:14:00)
接受答案了.

青云 (2002-12-23 9:25:00)
刚才我在局域网里试了一下,成功了,zw84611朋友提供的代码很有用,不过我觉得 这样
太麻烦,能不能直接用Udp控件实现该功能呢。
-----------
另外用tcp该怎么实现局域网广播啊,它和udp有什么区别啊。
-----------
有谁能争对zw84611朋友提供的代码给些注释和讲解。


zw84611的回答最终被接受。
 
话题1733139的标题是: 收听UDP广播 (100分)
分类:局域网 / 通讯 luxindelphi (2003-04-02 22:17:00)
怎样接收局域网中的UDP广播数据?

luxindelphi (2003-04-02 22:20:00)
在线等

zw84611 (2003-04-02 22:21:00)
端口一样即可接收。

luxindelphi (2003-04-02 22:22:00)
我不知道怎么实现,能否给个例子

luxindelphi (2003-04-02 22:28:00)
是不是必须知道发送广播的地址?

purwind (2003-04-02 22:32:00)
只要往 子网掩码 发送就是广播了

luxindelphi (2003-04-02 22:38:00)
我是要接收数据。能否给个例子?

nibul (2003-04-02 22:39:00)
根据TCP/IP协议,如果你的子网掩码为255.255.255.0
那么它的广播地址是:192.168.0.255你向这个地址发送消息就可以了,
然后这个网段上的机器都会收到的。
根据子网掩码不同,你的广播地址也就不一样。

luxindelphi (2003-04-02 22:40:00)
接收数据时,是不是也接收192。168。0。255的数据就可以了?

zw84611 (2003-04-02 22:41:00)
比如用NMUDP,你必须设置好它的LocalPort属性,使它和广播数据的端口一样。

procedure TForm1.NMUDP1DataReceived(Sender: TComponent; NumberBytes: Integer; FromIP: String; Port: Integer);
var
C: array [1..3] of Char;
I: Integer;
begin
if NumberBytes <= 3 then
begin
NMUDP1.ReadBuffer(C, I);
Memo1.Lines.Add(C+': received '+IntToStr(I)+' bytes from '+FromIP+' on port '+IntToStr(Port));
end
else
Memo1.Lines.Add(IntToStr(I)+' bytes incoming, buffer too small');
end;



nibul (2003-04-02 22:43:00)
你要知道UDP协议的原理,
它就是在这个网段上向1~254上发送消息

nibul (2003-04-02 22:45:00)
给我你的EMAIL,我发个例子给你

luxindelphi (2003-04-02 22:51:00)
smart.lu@163.com,多谢!!!

zw84611 (2003-04-02 22:55:00)
“向1~254上发送消息”这个说法不妥,广播只需发送一次,本子网内的所有机器都能收到。


luxindelphi (2003-04-02 23:07:00)
to nibul:
收不到你的邮件呀,老兄你发了没有。

luxindelphi (2003-04-02 23:10:00)
其它兄弟也别闲着,我看到答案立马给分。在线等,拜托!

luxindelphi (2003-04-02 23:44:00)
各位,我已经知道怎么做了,虽然没有给我具体说明,但大家还是给了我提示,
感谢!!!!分数我给NIBUL和ZQ84611。

luxindelphi (2003-04-02 23:45:00)
多人接受答案了。


nibul-30,purwind-10,zw84611-60,的回答最终被接受。
 
其实直接使用socket就可以ok
 
我用的是DELPHI7,INDY目录下没有,
 
服务端用的是6008端口发送,

我的客户端也要是6008端口吗?
 
对,端口要一样
 
后退
顶部