接收来自N个客户端的响应,以响应UDP上的广播请求

我正在为特定类型的网络多媒体设备实现一种IP查找器。 我想找出局域网中所有类型的活动设备,包括它们的IP地址和其他细节。

该设备有自己的设备发现方式。

它的工作原理如下:客户端通过UDP通过LAN发送广播请求。
目标端口号是固定的。
作为回应,LAN中理解此请求格式的所有服务器都将响应此请求,提供有关自身的信息。

我正在使用sendto()广播UDP请求消息。

现在我的问题是我不知道有多少设备(ieservers)会响应请求。

我需要多少次调用recvfrom()?
我什么时候才能知道我已经处理了所有设备的响应?
或者一般来说,recvfrom()是从多个服务器接收响应的正确选择吗?
有没有更好的(或者如果我错在这里是正确的)完成相同的方式?

我正在用C / C ++编程,计划为Windows和Linux编写代码。
提前谢谢了。

编辑:所以在这里所有的网络编程向导的帮助下,我找到了我的问题的解决方案:)
select()对我来说就是这个……
非常感谢所有花时间帮助我的人

我需要多少次调用recvfrom()? 我什么时候才能知道我已经处理了所有设备/服务器的响应?

如果您不知道设备/服务器的数量,则无法知道需要调用recvfrom()或处理所有响应的次数。

您可以考虑使用select()循环(直到超时)并在数据可供读取时调用recvfrom() 。 这可能在主线程或单独的线程中。

如果数据的到达速度快于处理速度,则会丢失数据报。 这在很大程度上取决于数据在接收后解析和存储的速度。 如果处理数据是密集操作,则可能需要在单独的线程中执行处理或存储数据,直到接收循环超时,然后继续处理它。

由于UDP不可靠,循环重播几次应该有助于解决部分损失,处理应该考虑重复。

以下伪代码是我如何解决问题:

 /* get socket to receive responses */ sd = socket( ... ); do { /* set receive timeout */ timeout.tv_sec = 5; /* broadcast request */ sendto( ... ); /* wait for responses (or timeout) */ while(select(sd+1, &readfds, NULL, NULL, &timeout) > 0) { /* receive the response */ recvfrom( ... ); /* process the response (or queue for another thread / later processing) */ ... /* reset receive timeout */ timeout.tv_sec = 5; } /* process any response queued for later (and not another thread) */ } while (necessary); 

或者一般来说,recvfrom()是从多个服务器接收响应的正确选择吗?

recvfrom()通常与无连接模式套接字一起使用,因为它允许应用程序检索接收数据的源地址。

在循环中使用带有超时的select(2)/poll(2) ,每次从设备获得响应时都会减少超时。 你必须自己想出适当的超时。

或者,如果您能够识别/解析发现响应消息,则只需在收到此类消息后将设备添加到列表中。

无论如何,当设备注册但稍后失败时,您可能不得不处理超时。

如果您不知道有多少服务器要响应,那么您不知道必须调用recvfrom()多少次。 我可能会用一个带有合适超时的select()循环处理这个问题,如下所示,这是完全未经测试的,可能充满了愚蠢的错误:

 /* create and bind socket */ fd_set fds; struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(sock, &fds); int ret; while((ret = select(sock + 1, &fds, NULL, NULL, &tv)) > 0) { char buf[BUFLEN]; struct sockaddr addr; if(recvfrom(sock, buf, BUFLEN, MSG_DONTWAIT, &addr, sizeof(struct sockaddr)) > 0) { /* handle response */ } else { /* handle error */ } } if(ret < 0) { /* handle error */ } else { /* select() timed out; we're theoretically done */ } 

这将继续调用recvfrom()直到2秒没有收到回复,这当然意味着它将阻塞至少2秒。 根据底层协议的不同,您可以使用更短的超时时间; 事实上,你可以减少每个回复。 需要进行一些测试和调整才能找到最佳配置。 您无需担心服务器同时响应; 以太网层将处理它。

你无法知道。 它不可知。

据推测,从你的描述: I want to find out all the alive devices ,设备可以随时从死亡转为活着,然后再回来。 这意味着您将不得不连续轮询:即每隔几秒发送一次广播请求(但不要太频繁)并查看谁响应。

如果我有这个权利,那UDP本质上是不可靠的,你将不得不在UDP之上改编一些可靠性:

  • 每隔几秒发送一次广播,因为设备可能不会每次都收到广播。
  • 您可能不会收到他们的回复,但您可能会在下一次收到回复。
  • 回复确认设备处于活动状态。
  • 在声明设备死机之前等待’n’无响应。

你知道可能的设备的最大数量吗? 如果你这样做,你可能会发现你必须多次调用recvfrom()。