1

I need to implement following behavior: when server starts, it should check for existing servers using broadcast. Then it waits for answer.

But, how to set any timeout for waiting?

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);
Christophe
  • 68,716
  • 7
  • 72
  • 138
Evgeniy175
  • 324
  • 1
  • 9
  • 23

2 Answers2

2

The common way is to use select() or poll() to wait for an event on a set of filedescriptors. These functions also allow you to specify a timeout. In your case, add the following before the recvfrom() call:

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

This will wait 1000 milliseconds. This will exit when a packet has arrived on socket s, or after 1 second, whichever comes first. You can check the return value of poll() to see if it returned because of a packet or because of a timeout.

G. Sliepen
  • 7,637
  • 1
  • 15
  • 31
  • Right idea, unfortunately with the designated initializer list you trip over one of the syntax differences between C and C++. – user4581301 Oct 03 '16 at 22:03
  • @user4581301: it's valid in both C99 and C++11. – G. Sliepen Oct 04 '16 at 17:22
  • There was talk about slipping it into C++14, but as of C++17 drafts I'm still not seeing it in [dcl.init.aggr]. GCC appears to offer it as an extension. – user4581301 Oct 04 '16 at 18:11
  • Though it looks like some wording was changed to explicitly state what happens to `revents` if you `struct pollfd pfd = {s, POLLIN};`. reads like it is treated as ``struct pollfd pfd = {s, POLLIN, {}};`` which should give 0. – user4581301 Oct 04 '16 at 18:30
1

Set a read timeout with setsockopt() and SO_RCVTIMEO, and handle EAGAIN/EWOULDBLOCK which occurs if the timeout is triggered.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • SO_RCVTIMEO works only for recv() , or not? This tells here https://msdn.microsoft.com/en-us/library/windows/desktop/ms740476(v=vs.85).aspx – Evgeniy175 Oct 04 '16 at 15:53
  • It works for any of the `recv()` family of methods, and also for `read()` except in Winsock systems. – user207421 Oct 05 '16 at 07:44
  • @user207421 How do we 'handle' the `EAGAIN/EWOULDBLOCK` as I have set the timeout but my `recvfrom` seems to be ridiculously slow – jjmcc Aug 18 '18 at 17:33