I'm implementing server which initializes listener like this (err handling omitted):
struct event_base* base = event_base_new();
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(8444);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
struct evconnlistener* listener = evconnlistener_new_bind(base, HandleAccept, ctx,
LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
-1,
(struct sockaddr*)&sin, sizeof(sin));
evconnlistener_set_error_cb(listener, HandleAcceptError);
event_base_dispatch(base);
evconnlistener_free(listener);
event_base_free(base);
I need to support both Linux & Windows. Server process might be killed abruptly at any moment and it should be possible to restart it quickly - hence LEV_OPT_REUSABLE (I think that details are not that important, we are using it in our test setup, server is started&killed by python).
On Linux this behaves as I expect, on Windows I'm getting 10048 (Only one usage of each socket address (protocol/network address/port) is normally permitted.) from evconnlistener_new_bind.
I've learned that SO_REUSEADDR on Unix and on Windows are different and tracked down my problem down to
|
int |
|
evutil_make_listen_socket_reuseable(evutil_socket_t sock) |
|
{ |
|
#if defined(SO_REUSEADDR) && !defined(_WIN32) |
|
int one = 1; |
|
/* REUSEADDR on Unix means, "don't hang on to this address after the |
|
* listener is closed." On Windows, though, it means "don't keep other |
|
* processes from binding to this address while we're using it. */ |
|
return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one, |
|
(ev_socklen_t)sizeof(one)); |
|
#else |
|
return 0; |
|
#endif |
|
} |
which causes the
LEV_OPT_REUSEABLE to do nothing on Windows.
I assume this is intentional but:
- this behavior could be documented better in
|
/** Flag: Indicates that we should disable the timeout (if any) between when |
|
* this socket is closed and when we can listen again on the same port. */ |
|
#define LEV_OPT_REUSEABLE (1u<<3) |
- perhaps dedicated flag which does set
SO_REUSEADDR on Windows could be added so it is possible to use this nice utility function for both platforms - by all means, I'm not an expert, my main complaint here is about documentation - but giving user a choice seems reasonable here.
I'm implementing server which initializes listener like this (err handling omitted):
I need to support both Linux & Windows. Server process might be killed abruptly at any moment and it should be possible to restart it quickly - hence
LEV_OPT_REUSABLE(I think that details are not that important, we are using it in our test setup, server is started&killed by python).On Linux this behaves as I expect, on Windows I'm getting
10048 (Only one usage of each socket address (protocol/network address/port) is normally permitted.)fromevconnlistener_new_bind.I've learned that
SO_REUSEADDRon Unix and on Windows are different and tracked down my problem down tolibevent/evutil.c
Lines 480 to 493 in a994a52
which causes the
LEV_OPT_REUSEABLEto do nothing on Windows.I assume this is intentional but:
libevent/include/event2/listener.h
Lines 69 to 71 in a994a52
evutil_make_listen_socket_reuseabledescription (https://libevent.org/libevent-book/Ref5_evutil.html) although it is not most fortunate place for that.SO_REUSEADDRon Windows could be added so it is possible to use this nice utility function for both platforms - by all means, I'm not an expert, my main complaint here is about documentation - but giving user a choice seems reasonable here.