我正在为特定类型的网络多媒体设备实现一种IP查找器。 我想找出局域网中所有这种类型的活动设备,包括它们的IP地址和其他细节。
设备有自己的设备发现方式。
它的工作原理如下: 客户端通过UDP通过LAN发送广播请求 目标端口号是固定的 作为回应,局域网中理解此请求格式的所有服务器都将响应此请求,提供有关自身的信息。
我正在使用sendto()广播UDP请求消息。
现在我的问题是我不知道有多少设备(ieservers)会响应请求。
我需要多少次调用recvfrom()?
我什么时候才能知道我已经处理了所有设备的响应? 或者一般来说,recvfrom()是从多个服务器接收响应的正确选择吗? 有没有更好的(或者如果我错在这里是正确的)完成相同的方式?
我正在用C / C ++编程,计划为Windows和Linux编写代码 非常感谢提前。
编辑:
所以在这里所有网络编程向导的帮助下,我找到了解决问题的方法:)
select()对我来说就是这个......
非常感谢所有花时间帮助我的人
答案 0 :(得分:2)
我需要多少次调用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()
通常用于无连接模式套接字,因为它允许应用程序检索接收数据的源地址。
答案 1 :(得分:2)
在循环中使用带有超时的select(2)/poll(2)
,每次从设备获得响应时都会减少超时。你必须自己想出适当的超时。
或者,如果您能够识别/解析发现响应消息,只需在收到此消息后将设备添加到列表中。
无论如何,您可能必须处理设备注册时的超时,但稍后会失败。
答案 2 :(得分: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秒。根据底层协议的不同,您可以使用更短的超时时间;事实上,你可以减少每个回复。需要进行一些测试和调整才能找到最佳配置。您无需担心服务器同时响应;以太网层将处理它。
答案 3 :(得分:0)
你无法知道。它不可知。
据推测,根据你的描述:I want to find out all the alive devices
,设备可以随时从死亡转为活着,然后再返回。这意味着您将不得不连续轮询:即每隔几秒发送一次广播请求(但不要太频繁)并查看谁回应。
如果我说得对,那UDP本质上是不可靠的,你将不得不在UDP之上改编一些可靠性:
您知道可能的设备的最大数量吗?如果你这样做,你可能会发现你必须多次调用recvfrom()。