Если вы не знаете, сколько серверов будет отвечать, то вы не знаете, сколько раз вам нужно вызывать 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 секунды. В зависимости от базового протокола, вы, вероятно, можете использовать намного более короткий тайм-аут; действительно, вы можете уменьшить его при каждом ответе. Некоторое тестирование и настройка потребуются, чтобы найти оптимальную конфигурацию. Вам не нужно беспокоиться о одновременной реакции серверов; уровень Ethernet справится с этим.