如何使用IDUDPServer控件往多网卡中发广播包

张飞吃虾 2014-09-11 02:48:35
我有一个装置是这样与其建立连接的:
上位机通过IDUDPServer发广播->装置收到广播后向上位机请求建立TCP连接->上位机的IDTCPServer检测到连接请求后建立连接。
现在我的问题是电脑有两个网卡,其中一个网卡连接该装置,我发广播包的时候如何能保证广播包从连接装置的网卡发出去,或者从两个网卡都发出去?
我的指令如下:
IDUDPServer1->sendbuffer("255.255.255.255",6000,DF);
在线等,如果有大神详细解释bindings、binding的区别,控件属性栏中DefaultPort、bingding中的Port的区别,给100分!
...全文
1103 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
pzf01 2015-05-19
  • 打赏
  • 举报
回复
//经过试验,当UDP的数据包Socket不调用Bind绑定到某一个指定的网卡时,多网卡环境下 //发送广播数据包时,将由操作系统底层选择一个网卡来发,而不是系统存在的网卡都发 //通常系统自选的,是在网络适配器列表中的第一个位置的网卡。这会导致广播数据包不从希望的网卡发出 //导致和此网卡连接的其他设备无法收到此广播包,而无法应答,系统和这些设备无法通信 //解决办法是强制设定Binding.IP(本机指定网卡的IP)并调用Binding.Bind(通常的UDP通信并不需要Bind) //此后发出的广播包则只会从指定网卡走了。 //有指定目的地PeerIP,PeerPort的非广播包,则系统根据当前路由表自动选择路径最近的网卡发送。 我有一个这方面的应用,要从里面抠出来作为一个完整的例子比较难,简单讲一下: 首先有个画面,姑且叫配置画面,让用户选一个网卡(当然之前,你要准备一个网卡列表),如下: cbNic: TComboBox; 使用这个函数填充它,然后让用户选, GetNetcardIP('',cbNic.Items); //根据网卡名字找到网卡IP地址,或填充所有网卡名字到NICList function GetNetcardIP(NICName:string; NICList:Tstrings=nil):string; var ulSize:integer; pmem:Pointer; pInfo:PIP_ADAPTER_INFO; pIPAD:PIP_ADDR_STRING; i: integer; mac,nic:string; begin Result := ''; pInfo := nil; GetAdaptersInfo(pInfo,ulSize);//第一次调用,获取缓冲区大小 GetMem(pInfo,ulSize); pmem := pInfo; try i := GetAdaptersInfo(pInfo,ulSize); if i<>0 then Exit; //获取网络列表失败 while(pInfo<>nil) do begin //遍历每一张网卡 pInfo->Address 是MAC地址 mac := ''; for i:=0 to pInfo^.AddressLength-1 do mac := mac+InttoHex(pInfo^.Address[i],2)+':'; nic := pInfo^.Description; i := Pos(' - ',nic); if i<>0 then SetLength(nic,i-1); //删除' - 数据包计划程序微型接口'之类的文字 if NICList<>nil then NICList.Add(nic); pIPAD := pInfo^.CurrentIpAddress; //CurrentIpAddress通常nil while pIPAD<>nil do begin pIPAD := pIPAD^.Next; end; pIPAD := @pInfo^.IpAddressList; if (NICName=nic) and (pIPAD<>nil) then begin Result := pIPAD^.IpAddress; break; end; repeat pIPAD := pIPAD^.Next; until pIPAD=nil; pIPAD := @pInfo^.GatewayList; repeat pIPAD := pIPAD^.Next; until pIPAD=nil; pIPAD := @pInfo^.DhcpServer; repeat pIPAD := pIPAD^.Next; until pIPAD=nil; if pInfo^.HaveWins<>0 then begin pIPAD := @pInfo^.PrimaryWinsServer; repeat pIPAD := pIPAD^.Next; until pIPAD=nil; pIPAD := @pInfo^.SecondaryWinsServer; repeat pIPAD := pIPAD^.Next; until pIPAD=nil; end; pInfo := pInfo^.Next; end; finally FreeMem(pmem); end; end; 用户选完以后(窗口关闭的时候,用下面的代码获得用户的选择:BindNICChanged是一个自定义的标志,识别网卡选择的改变 BindNIC := cbNic.Text; BindNICChanged := True; 这个就是我们要绑定的网卡名称,创建一个UDP客户端 fComm := TIdUDPClient.Create(nil); fComm.Port := 1111; fComm.ReceiveTimeout := 500; 根据NIC名称,获得其IP地址,并在这个网卡上发送广播包出去 if BindNICChanged then begin BindNICChanged := False; fComm.Active := False; //网络通信Socket关闭 hostip := GetNetcardIP(BindNIC); if hostip<>'' then begin fComm.Binding.IP := hostip; //指定需要绑定通信的网卡IP地址:调用Binding,将自动重开网络 fComm.Binding.Bind; //绑定本机IP地址 end; fComm.Active := True; //网络通信Socket开启 end; fComm.Broadcast(strs,PeerPort); //全网广播UDP包命令数据 MultiReceive := True; end else fComm.Send(PeerIP,PeerPort,strs); //普通发送UDP包命令数据 Sleep(10); //适当延迟,避免下位机负载过重 接收用这个: strs := fComm.ReceiveString(PeerIP,PeerPort,500); 收到了,那么PeerIP就知道了,以后就用普通发送就可以了。 fComm.Send(PeerIP,PeerPort,strs); //普通发送UDP包命令数据 PeerPort可以和本机的fComm.Port := 1111;不一样,也可以一样,随便
张飞吃虾 2015-04-08
  • 打赏
  • 举报
回复
引用 23 楼 whustriker 的回复:
引用 22 楼 kfrght 的回复:
楼Z太猛了,典型的黑名单人物
啥意思,是分没给到吗
真没给到,太抱歉了,分欠着你的,怎么还给你?
张飞吃虾 2015-04-08
  • 打赏
  • 举报
回复
引用 22 楼 kfrght 的回复:
楼Z太猛了,典型的黑名单人物
啥意思,是分没给到吗
宝龙哥 2014-10-01
  • 打赏
  • 举报
回复
楼Z太猛了,典型的黑名单人物
张飞吃虾 2014-09-30
  • 打赏
  • 举报
回复
引用 20 楼 kfrght 的回复:
[quote=引用 18 楼 whustriker 的回复:] [quote=引用 14 楼 hyz_cs 的回复:] [quote=引用 13 楼 whustriker 的回复:] [quote=引用 12 楼 kfrght 的回复:] 你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。[/quote] 获取IP和子网掩码自己计算相应的广播地址。[/quote] 设备的IP和子网掩码获取不了哦,请看上面的回复。 而且获取了也没用,因为要向255.255.255.255发广播才有效,而不是发到某个广播地址。 我的根本需求就是同时向两个网卡发送UDP广播: IDUDPServer1->sendbuffer("255.255.255.255",6000,DF); 能不能解决,大神?[/quote] 奇才啊,兄弟,这样的需求你都能遇到,不过上面已经说了,你需要绑定网卡,然后发送: 假设有两个IP地址,如果不配置Bindings属性的话UDPServer将监听来自这两个IP的连接,如果你绑定了IP,UDPServer就只监听来自绑定Bindings(存储绑定好的连接的列表)的IP的请求。 大概类似上面的[/quote]好,多谢你了。
宝龙哥 2014-09-29
  • 打赏
  • 举报
回复
引用 18 楼 whustriker 的回复:
[quote=引用 14 楼 hyz_cs 的回复:] [quote=引用 13 楼 whustriker 的回复:] [quote=引用 12 楼 kfrght 的回复:] 你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。[/quote] 获取IP和子网掩码自己计算相应的广播地址。[/quote] 设备的IP和子网掩码获取不了哦,请看上面的回复。 而且获取了也没用,因为要向255.255.255.255发广播才有效,而不是发到某个广播地址。 我的根本需求就是同时向两个网卡发送UDP广播: IDUDPServer1->sendbuffer("255.255.255.255",6000,DF); 能不能解决,大神?[/quote] 奇才啊,兄弟,这样的需求你都能遇到,不过上面已经说了,你需要绑定网卡,然后发送: 假设有两个IP地址,如果不配置Bindings属性的话UDPServer将监听来自这两个IP的连接,如果你绑定了IP,UDPServer就只监听来自绑定Bindings(存储绑定好的连接的列表)的IP的请求。 大概类似上面的
hyz_cs 2014-09-29
  • 打赏
  • 举报
回复
引用 18 楼 whustriker 的回复:
[quote=引用 14 楼 hyz_cs 的回复:] 而且获取了也没用,因为要向255.255.255.255发广播才有效,而不是发到某个广播地址。 我的根本需求就是同时向两个网卡发送UDP广播: IDUDPServer1->sendbuffer("255.255.255.255",6000,DF); 能不能解决,大神?
分开发,192.168.1.255/192.168.2.255
张飞吃虾 2014-09-29
  • 打赏
  • 举报
回复
引用 14 楼 hyz_cs 的回复:
[quote=引用 13 楼 whustriker 的回复:] [quote=引用 12 楼 kfrght 的回复:] 你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。[/quote] 获取IP和子网掩码自己计算相应的广播地址。[/quote] 设备的IP和子网掩码获取不了哦,请看上面的回复。 而且获取了也没用,因为要向255.255.255.255发广播才有效,而不是发到某个广播地址。 我的根本需求就是同时向两个网卡发送UDP广播: IDUDPServer1->sendbuffer("255.255.255.255",6000,DF); 能不能解决,大神?
张飞吃虾 2014-09-29
  • 打赏
  • 举报
回复
引用 15 楼 kfrght 的回复:
[quote=引用 13 楼 whustriker 的回复:] [quote=引用 12 楼 kfrght 的回复:] 你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。[/quote] 这个不是什么难事,只有两个网卡,连接了那个设备后总有一个标识,比如设备名称等,在两个网段ping这个设备名就可以了,实在不行的话分别向两个网段广播就是了[/quote]
引用 15 楼 kfrght 的回复:
[quote=引用 13 楼 whustriker 的回复:] [quote=引用 12 楼 kfrght 的回复:] 你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。[/quote] 这个不是什么难事,只有两个网卡,连接了那个设备后总有一个标识,比如设备名称等,在两个网段ping这个设备名就可以了,实在不行的话分别向两个网段广播就是了[/quote] 没有你想的那么简单哦,设备在收到广播之前是没有IP地址的,整个连接流程是这样的: 设备(等待UDP广播)->上位机发送UDP广播到255.255.255.255->设备创建Tcp客户端,并向上位机发送连接请求->上位机TcpServer收到连接请求创建连接,开始通信。 因此,我的根本需求就是同时向两个网卡发送UDP广播: IDUDPServer1->sendbuffer("255.255.255.255",6000,DF); 能不能解决,大神?
张飞吃虾 2014-09-29
  • 打赏
  • 举报
回复
引用 15 楼 kfrght 的回复:
[quote=引用 13 楼 whustriker 的回复:] [quote=引用 12 楼 kfrght 的回复:] 你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。[/quote] 这个不是什么难事,只有两个网卡,连接了那个设备后总有一个标识,比如设备名称等,在两个网段ping这个设备名就可以了,实在不行的话分别向两个网段广播就是了[/quote] 你好,我的这个下位机是这样的:只有上位机向255.255.255.255发广播给它,它才会反馈信息到上位机。因此不能按照你说的那个方法。
宝龙哥 2014-09-28
  • 打赏
  • 举报
回复
引用 13 楼 whustriker 的回复:
[quote=引用 12 楼 kfrght 的回复:] 你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。[/quote] 这个不是什么难事,只有两个网卡,连接了那个设备后总有一个标识,比如设备名称等,在两个网段ping这个设备名就可以了,实在不行的话分别向两个网段广播就是了
hyz_cs 2014-09-27
  • 打赏
  • 举报
回复
引用 13 楼 whustriker 的回复:
[quote=引用 12 楼 kfrght 的回复:] 你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。[/quote] 获取IP和子网掩码自己计算相应的广播地址。
张飞吃虾 2014-09-22
  • 打赏
  • 举报
回复
引用 12 楼 kfrght 的回复:
你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
设备的网段不知道哦,是随机的。设备通过网线直连到电脑上。
宝龙哥 2014-09-19
  • 打赏
  • 举报
回复
你通过网段来发广播就可以了,比如设备在192.168.1网段,那么,你广播到192.168.1这个网段就行
张飞吃虾 2014-09-19
  • 打赏
  • 举报
回复
引用 9 楼 kfrght 的回复:
这个你分别ping两个网段的其它计算机的ip地址看是否两个都能同时拼通
请问大侠,计将安出?
张飞吃虾 2014-09-13
  • 打赏
  • 举报
回复
引用 9 楼 kfrght 的回复:
这个你分别ping两个网段的其它计算机的ip地址看是否两个都能同时拼通
是都能ping通。
张飞吃虾 2014-09-12
  • 打赏
  • 举报
回复
引用 5 楼 kfrght 的回复:
DefaultPort 自己服务端开的自己用的端口 Bindings是 TIdSocketHandles类型 是一个列表,存储着TIdSocketHandle连接的实例 Binding 是 TIdSocketHandle类型 ,只读属性,指向连接的socket句柄。 binding 是对进入数据包的绑定,也就是别人的IP端口。 defaultport 是自己的 binding 端口,是自己发送或接收信息所用的端口 假设有两个IP地址,如果不配置Bindings属性的话UDPServer将监听来自这两个IP的连接,如果你绑定了IP,UDPServer就只监听来自绑定Bindings(存储绑定好的连接的列表)的IP的请求。 UDPSERVER 的 UDP 广播一般用于同一IP段,跨网不行,跨网段(跨路由器)的话,则路由器必须支持IGMP协议
还有两个问题:1,binding里面有PeerIp和peerport,代表收到的数据来源地址,是只读属性;binding里面还有Ip和port,代表本机的Ip地址和端口,是可以设置的,这个port和defaultport有什么区别?2,我在binding里绑定了网卡2的IP地址,但是他还是从网卡1发出去,说明这不是解决办法。
张飞吃虾 2014-09-12
  • 打赏
  • 举报
回复
引用 5 楼 kfrght 的回复:
DefaultPort 自己服务端开的自己用的端口 Bindings是 TIdSocketHandles类型 是一个列表,存储着TIdSocketHandle连接的实例 Binding 是 TIdSocketHandle类型 ,只读属性,指向连接的socket句柄。 binding 是对进入数据包的绑定,也就是别人的IP端口。 defaultport 是自己的 binding 端口,是自己发送或接收信息所用的端口 假设有两个IP地址,如果不配置Bindings属性的话UDPServer将监听来自这两个IP的连接,如果你绑定了IP,UDPServer就只监听来自绑定Bindings(存储绑定好的连接的列表)的IP的请求。 UDPSERVER 的 UDP 广播一般用于同一IP段,跨网不行,跨网段(跨路由器)的话,则路由器必须支持IGMP协议
非常感谢你的回答,不过实际情况和你说的好像不太一样哟: 我的一个网卡1的IP是192.168.40.110,网卡2的IP地是192.168.1.35; 网卡2接的装置,我发送UDP广播后,通过抓包发现是从192.168.40.110这个网卡发出去的。
宝龙哥 2014-09-12
  • 打赏
  • 举报
回复
这个你分别ping两个网段的其它计算机的ip地址看是否两个都能同时拼通
宝龙哥 2014-09-12
  • 打赏
  • 举报
回复
这个你分别ping两个网段的其它计算机的ip地址看是否两个都能同时拼通
加载更多回复(5)

1,316

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧