I'm working on a multi-processes socket server with the boost library.
Each process run a io_service
.
I want to this processes all accept on the same port.
I know SO_REUSEPORT
(after linux kernel 3.9) will help.
like this python script
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind(('0.0.0.0', 9091))
s.listen(1)
while True:
conn, addr = s.accept()
print "new connection"
while True:
data = conn.recv(100)
print "got data", data
if not data or data == 'exit':
break
conn.close()
But I don't know how to use this option in boost asio io_service ?
For people reading this in 2019: Asio now includes a workaround in boost/asio/detail/impl/socket_ops.ipp
:
#if defined(__MACH__) && defined(__APPLE__) \
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
// To implement portable behaviour for SO_REUSEADDR with UDP sockets we
// need to also set SO_REUSEPORT on BSD-based platforms.
if ((state & datagram_oriented)
&& level == SOL_SOCKET && optname == SO_REUSEADDR)
{
call_setsockopt(&msghdr::msg_namelen, s,
SOL_SOCKET, SO_REUSEPORT, optval, optlen);
}
#endif
So, socket_->set_option(udp::socket::reuse_address(true));
will set the SO_REUSEPORT
option automatically if needed.
Following on from how boost/asio/socket_base.hpp defines reuse_address, I did it like this:
typedef boost::asio::detail::socket_option::boolean<SOL_SOCKET, SO_REUSEPORT> reuse_port;
socket_.set_option(reuse_port(true));
Answer by my own.
#include <iostream>
#include <string>
#include <array>
#include <boost/asio.hpp>
#include <arpa/inet.h>
using boost::asio::ip::tcp;
int main()
{
boost::asio::io_service io;
tcp::acceptor acceptor(io);
acceptor.open(tcp::v4());
int one = 1;
setsockopt(acceptor.native_handle(), SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one));
acceptor.bind(tcp::endpoint(tcp::v4(), 9091));
acceptor.listen();
std::cout << "start" << std::endl;
for(;;)
{
tcp::socket socket(io);
acceptor.accept(socket);
std::cout << "new connections" << std::endl;
for(;;)
{
std::array<char, 4> buf;
boost::system::error_code error;
boost::asio::read(socket, boost::asio::buffer(buf), error);
if(error)
{
std::cout << "read error: " << error << std::endl;
break;
}
std::cout << "read: " << std::string(buf.data()) << std::endl;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With