作为这个问题的后续问题,我已经在我的本地机器上运行了一个解决方案,但是没有在网络上的机器上运行.
我不太了解那些基础知识以外的插座,所以请耐心等待.目标是让客户端在本地网络上查找服务器,这是一些剪切/粘贴/编辑代码的结果.
这是客户端代码:
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10294);
byte[] data = new byte[1024];
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 10);
string welcome = "What's your IP?";
data = Encoding.ASCII.GetBytes(welcome);
client.SendTo(data, data.Length, SocketFlags.None, ipep);
IPEndPoint server = new IPEndPoint(IPAddress.Any, 0);
EndPoint tmpRemote = (EndPoint)server;
data = new byte[1024];
int recv = client.ReceiveFrom(data, ref tmpRemote);
this.IP.Text = ((IPEndPoint)tmpRemote).Address.ToString(); //set textbox
this.Port.Text = …Run Code Online (Sandbox Code Playgroud) 在Java世界中,可靠多播的现代方法是什么?
在网上搜索,我想出了JGroups和JRMS.JGroups在我的情况下似乎有些过分(我希望有一组相同的节点,这些节点通过一起协作并通过通知每个现有节点来加入这个组).JRMS看起来已经死了.
我无法找到任何针对Java的PGM协议的特定实现.
我正在尝试使用以下代码连接到多播组:
int flag_on = 1; /* socket option flag */
struct sockaddr_in mc_addr; /* socket address structure */
char recv_str[MAX_LEN+1]; /* buffer to receive string */
int recv_len; /* length of string received */
char* mc_addr_str; /* multicast IP address */
unsigned short mc_port; /* multicast port */
struct sockaddr_in from_addr; /* packet source */
unsigned int from_len; /* source addr length */
mc_addr_str = ip; /* arg 1: multicast ip address */
mc_port = port; /* arg 2: multicast …Run Code Online (Sandbox Code Playgroud) 当我创建两个udp套接字并将它们绑定到INADDR_ANY和相同的端口号时.但其中一人加入了一个组播组.但是它们都可以从同一个组播组接收数据,即使其中一个套接字没有加入组播组.
这是一些用于设置多播接收器的Python代码.它在mac和linux上运行良好.
import socket, struct
ADDR='239.239.250.1'
PORT=8001
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((ADDR, PORT))
mreq = struct.pack("4sl", socket.inet_aton(ADDR), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
Run Code Online (Sandbox Code Playgroud)
但在Windows上运行时在绑定上收到错误10049.
Z:\winx>c:\Python27\python.exe q2.py
Traceback (most recent call last):
File "q2.py", line 11, in <module>
sock.bind((ADDR,PORT))
File "c:\Python27\lib\socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 10049] The requested address is not valid in its context
Run Code Online (Sandbox Code Playgroud)
Windows多播是否存在已知问题?如果没有,我可以采取哪些步骤进行诊断?
我试图在系统中的所有接口上收听多播,但只在我收到多播数据包的这个接口上进行响应。
我所做的是为每个接口创建一个套接字,问题就在这里开始了。
当我将接口绑定到 INADDR_ANY它时,它将接收所有接口的数据包并在默认接口上发送。如果我将端口绑定到特定接口,它将不会接收多播数据包(但它将能够在正确的接口上发送它)。
我试过设置选项,如IP_ADD_MEMBERSHIP或IP_MULTICAST_IF但没有成功。
我认为其他选项应该是创建一个套接字来接收所有接口的所有 ifs 和 senders 套接字,但是在这种方法中,我不知道输入了哪个 ifs 数据包......
代码示例(简化,没有错误处理和东西):
创建套接字:
//here i am looping over all interfaces from getifaddrs
struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr;
sockets[i] = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
setsockopt(sockets[i], SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
mreq.imr_multiaddr.s_addr=inet_addr(MDNS_ADDRESS);
mreq.imr_interface.s_addr=pAddr->sin_addr.s_addr;
setsockopt(sockets[i], IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
setsockopt(sockets[i], IPPROTO_IP, IP_MULTICAST_IF, &pAddr, sizeof(struct in_addr));
memset(&my_addr, 0, sizeof(struct sockaddr_in));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = INADDR_ANY; //or pAddr->sin_addr.s_addr;
my_addr.sin_port = htons(port);
bind(sockets[i], (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) …Run Code Online (Sandbox Code Playgroud) 这个问题是关于在同一主机内发送和接收多播,同时将其发送到其他主机。
即使经过数小时的谷歌搜索,我也无法弄清楚如何在同一主机内路由多播数据报..!
下面是问题的详细描述:
Linux 机器“A”通过电缆连接到交换机/路由器(我们称交换机/路由器为“R”)。
在 linux box A 中,我有一个进程(A0)将 UDP 数据包发送到多播地址“224.0.0.0”,端口 5000。
同样,在同一个框 A 中,我有两个进程(A1 和 A2),都连接到 224.0.0.0、端口 5000 并消耗 UDP 数据包。
现在,box A 中的内核如何管理路由?
因此,A0 发送了一个数据报,该数据报被 A1 和 A2 消费。这样的数据报是否进行往返 A --> R --> A ?
.. 或者“A”中的内核路由是否足够智能以避免这种不必要的往返?(即数据报由 A0 发送并立即被 A1 和 A2 消耗,永远不会离开 A)。
当然,可以通过为多播创建和强制执行环回设备来确保多播数据报永远不会离开 A:
sudo ifconfig lo multicast
sudo route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
Run Code Online (Sandbox Code Playgroud)
但是现在,如果我想在另一个 linux 机器中同时使用 UDP 数据报,比如说“B”,它们就无法到达那里。
因此,理想情况下,(1)在 A 中消耗的数据报永远不应该离开 A(即没有往返 A --> R --> A),而(2)在 B 中消耗的数据报应该正常地作为 A --> …
为了在通信1-> n中最佳地利用网络带宽,我需要使用多播.在具有IGMP侦听交换机的内部数据中心中,组播的优势是显而易见的.但是,在像AWS这样的IaaS中,这并不明显,因为我们从硬件基础架构中抽象出来.当您需要将大约400 Mbps传输到可能托管在任何物理服务器中的多个EC2实例时,问题就出现了.所以这就是为什么我要问AWS是否支持组播和IGMP监听.
我正在尝试提高在大型网络上运行的多播应用程序的性能(以减少其数据包丢失)
我的实验表明,在应用程序的第一次运行中,有一些丢失的数据包。但是当我在上次运行后再次运行应用程序时(有时也有一点延迟),没有丢包。虽然当我在长时间延迟(例如 20 分钟左右)后重新运行应用程序时,我再次看到数据包丢失。
当我检查他们的时间戳时,我看到丢失的数据包大部分是在开始时发送的数据包。所以看起来交换机或路由器需要一些预热!或其他东西(我不知道如何称呼这种现象)。
我检查了tcpdump结果,接收器应用程序收到的数据包数量与网络购物车收到的数据包数量完全相同。
我已经尝试了以下技巧: 1- 更改进程在不同 CPU 内核和调度策略上的关联性 2- 更改套接字描述符的优先级
改变套接字描述符的优先级已经使它变得更好(减少了丢失的数据包数量)但是在将优先级设置为高之后,再次有一些丢失的数据包)
// For example
MulticastSender multicast_sender;
multicast_sender.init();
// Here I need a function in order to find out the switch is already warmed up or not
while (some condition)
{
////
multicast_sender.send(something);
////
}
Run Code Online (Sandbox Code Playgroud)
我想知道是不是有任何可能的方法来添加一些代码来确定交换机(或路由器)是否已经预热!足够的?
遵循 iOS 14 阻止访问本地网络的新策略,访问本地网络需要 com.apple.developer.networking.multicast 特殊权限,并且此访问应由用户在授权对话框中确认。虽然这个新功能没有被彻底记录下来,但苹果工程师在论坛上表示,这个授权对话框弹出窗口只在应用尝试发送流量时触发,导致应用只读取网络的问题,如iOS 14 如何触发本地网络对话并检查用户回答?
不幸的是,发送一些数据以触发授权对话框的建议在我们的案例中似乎不起作用,因为我们从未出现过弹出对话框。
我们的应用程序通常只接收 UDP 广播(除少数情况外不发送)。我们已经获得了 com.apple.developer.networking.multicast 权利,将其添加到我们的应用程序权利中,在我们的 Info.plist 中添加了请求的 NSLocalNetworkUsageDescription 并使用 XCode 12.0 手动签署我们的应用程序,并使用包含此权利的配置文件(在这种情况下需要手动代码签名,如https://developer.apple.com/forums/thread/656773?answerId=628537022 中所示)。从那时起,情况有所改善,因为在添加权利之前完全阻止的 UDP 数据包接收有时开始工作,但不幸的是并非总是如此(iOS 14.0.1 上的情况似乎比 iOS 14 上和 iPhone 上比 iPad 上更糟)。
最重要的是,我们从未显示授权对话框,我们的应用程序在隐私/本地网络中未显示为已授权(即使 UDP 接收有效)。我们怀疑这可能是造成这种虚假接收问题的原因。由于似乎授权对话框只在发送数据时显示,我们配置我们的应用程序将数据发送到本地网络以尝试触发对话框,使用以下所有方法: