-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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: