2016-10-03 4 views
0

Мне нужно реализовать следующее поведение: при запуске сервера он должен проверять наличие существующих серверов с помощью широковещательной передачи. Затем он ждет ответа.C++ recvfrom timeout

Но как установить любой тайм-аут для ожидания?

int optval = 1; 
char buff[BUFF_SIZE]; 
SOCKADDR_IN addr; 
int length = sizeof(addr); 

if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&optval, sizeof(optval)) == SOCKET_ERROR) throw(errors::SETSOCKOPT); 

addr->sin_family = AF_INET; 
addr->sin_port = htons(this->serverPort); 
addr->sin_addr.s_addr = INADDR_ANY; 
sendto(s, this->serverName.c_str(), this->serverName.length() + 1, NULL, (SOCKADDR*)&addr, sizeof(addr)); 

memset(&addr, NULL, sizeof(addr)); 

recvfrom(s, buff, BUFF_SIZE, NULL, (SOCKADDR*)&addr, &length); 
+5

Вы можете использовать 'select (2)' или установить его в неблокирование и использовать 'epoll (2)' –

ответ

1

Установите тайм-аут чтения с setsockopt() и SO_RCVTIMEO и обработайте EAGAIN/EWOULDBLOCK, который возникает, если таймаут запускается.

+0

SO_RCVTIMEO работает только для recv(), или нет? Это говорит здесь https://msdn.microsoft.com/en-us/library/windows/desktop/ms740476(v=vs.85).aspx – Evgeniy175

+0

Это отлично работает, спасибо – Evgeniy175

+0

Он работает для любого из 'recv () 'семейства методов, а также для' read() ', за исключением систем Winsock. – EJP

0

Обычный способ заключается в использовании select() или poll() ждать события на множестве filedescriptors. Эти функции также позволяют указать тайм-аут. В вашем случае, добавьте следующую строку перед recvfrom() вызова:

struct pollfd pfd = {.fd = s, .events = POLLIN}; 
poll(&pfd, 1, 1000); 

Это будет ждать 1000 миллисекунд. Это выйдет, когда пакет поступит на сокет s или через 1 секунду, в зависимости от того, что наступит раньше. Вы можете проверить возвращаемое значение poll(), чтобы узнать, было ли оно возвращено из-за пакета или из-за таймаута.

+0

Правильная идея, к сожалению, с указанным списком инициализаторов вы преодолеваете одно из различий синтаксиса между C и C++. – user4581301

+0

@ user4581301: он действителен как на C99, так и на C++ 11. –

+0

Был разговор о том, чтобы сместить его в C++ 14, но по сравнению с C++ 17 черновиками я все еще не вижу его в [dcl.init.aggr]. GCC, похоже, предлагает его как расширение. – user4581301