-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
How to set SO_REUSEPORT #530
Comments
pre_init happens after bind/listen/accept, preventing socket options that affect those system calls from being set in time.
I pushed a change to develop branch that moves the socket_init_handler hook from the pre_init phase (which is after bind/listen/accept) to the init_asio phase, which is before. Can you test if this helps? |
I just tested it: Printing the native handle's value For a test I also set an asio option to see the values of the error code: ec result is So IMHO the reason is the socket, that is not initialised at that time. |
FYI Its the only location I found that: Can you change to have a signal handler called in the spot, where I added - admittedly not very nice - the setsockop() call? Thank you in advance! |
pre_init happens after bind/listen/accept, preventing socket options that affect those system calls from being set in time.
Please notice that the commit 6f128a5 broke my code using |
@vadz Did you manage to set the no_delay option? |
I didn't return to this code since then, so I only "managed" to do it by reverting the commit that broke it, as written above. |
This reverts commit 6f128a5.
Why is this still unfixed? I have same problem in latest master. NO_DELAY is pretty much the point of websockets in the first place, otherwise just use http polling. MatusKysel patch fixes it for me BTW: SophiaTX@c7783e2 Cleanest solution is probably to have a pre_init and post_init handler and also a way to determine if the passed socket is the actual listen_socket or not, since some options you wanna set on the listen_socket others on the accepted sockets. |
This regression introduced in 0.8.0 that broke setting socket options on already accepted connections has been fixed in the |
…s like TCP_NODELAY from being set. Improve documentation about how pre_init differs from init_asio. Improve documentation for the TCP pre-bind handler that is the actual solution to the issue this regression related to. references zaphoyd#530 fixes zaphoyd#812
I've encountered another issue in our server project: We need to set SO_REUSEPORT.
We already use endpoint:set_reuse_addr(true) with our TCP server (SOCK_STREAM), which partially helps. To solve the last issues we need to set SO_REUSEPORT.
The project uses the latest websocketpp 0.7.0 on Mac OS X.
As suggested I already uses the socket_init_handler ([http://stackoverflow.com/questions/23023317/proper-set-socket-init-handler-syntax-or-modify-source-to-turn-on-tcp-nodelay-wi/23031124#23031124] and [https://groups.google.com/forum/#!msg/websocketpp/rvBcIJ940Bc/zxpZf9AOb0IJ]).
I've also set the tcp_pre_init_handler.
The modified websocketpp-provided example "echo_server.cpp" shows the issue quite nicely; I've added the following lines:
`
void on_socket_init(websocketpp::connection_hdl hdl, boost::asio::ip::tcp::socket & s)
{
std::cerr << "on_socket_init...\n";
int reuse = 1;
int ihdl = s.lowest_layer().native_handle();
if (setsockopt(ihdl, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
perror(“setsockopt(SO_REUSEADDR) failed");
}
...
echo_server.set_socket_init_handler(bind(&on_socket_init, ::_1, ::_2));
//echo_server.set_tcp_pre_init_handler(bind(&on_tcp_init, ::_1));
...
std::cerr << "pre listen...\n";
echo_server.listen(9002);
std::cerr << "post listen...\n";
...
`
Starting a second instance of the server, it fails with
[info] asio listen error: system:48 (Address already in use) Underlying Transport Error
Unfortunately the handlers are called when the first client connects and therefore after endpoint.listen(), which actually creates the socket, sets SO_REUSEADDR and bind()s the socket.
Trying to set SO_REUSEPORT in the handler has no effect.
The output before a client has connected:
pre listen... post listen...
As soon as a client connects:
on_socket_init...
When adding tcp_pre_init_handler as well, I can observe it being called even after on_socket_init.
By modifying (as a test) the boost::asio code to also set SO_REUSEPORT for TCP/non-datagram oriented sockets, I can see that starting two (or more) instances of the server then is possible.
(How) is it possible to set SO_REUSEPORT before the bind() takes place?
If this is currently not possible, can you please add a callback / another handler (preferably already providing the socket like the init_socket_handler), which gets called in endpoint.listen() after
m_acceptor->open(ep.protocol(),bec);
and before
m_acceptor->bind(ep,bec);
Many thanks in advance!
The text was updated successfully, but these errors were encountered: