Below is my sample code for socket server using boost asio.
This server will wait on port 10001 for any client to connect. When any client connects it will start thread to read from that client and wait for another client. But what happens when my client disconnects the server socket hangs in my_socket->close()
call.
And if new client tries to connect the server crashes.
I am using g++ (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <sys/socket.h>
#include <unistd.h>
#include <string>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
using namespace std;
using boost::asio::ip::tcp;
void run(boost::shared_ptr<tcp::socket> my_socket)
{
while (1)
{
char buf[128];
boost::system::error_code error;
size_t len = my_socket->read_some(boost::asio::buffer(buf, 128), error);
std::cout << "len : " << len << std::endl;
if (error == boost::asio::error::eof)
{
cout << "\t(boost::asio::error::eof)" << endl;
if (my_socket->is_open())
{
boost::system::error_code ec;
cout << "\tSocket closing" << endl;
my_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
cout << "\tShutdown " << ec.message() << endl;
// cout << "normal close : " << ::close(my_socket->native_handle()) << endl;
my_socket->close(ec);
cout << "\tSocket closed" << endl;
}
break; // Connection closed cleanly by peer.
}
else if (error)
{
std::cout << "Exception : " << error.message() << std::endl;
break;
}
else
{
for (unsigned int i = 0; i < len; i++)
printf("%02x ", buf[i] & 0xFF);
printf("\n");
}
}
}
int main()
{
const int S = 1000;
vector<boost::shared_ptr<boost::thread> > arr_thr(S);
try
{
for (uint32_t i = 0;; i++)
{
boost::asio::io_service io_service;
tcp::endpoint endpoint(tcp::v6(), 10001);
boost::shared_ptr<tcp::socket> my_socket(new tcp::socket(io_service));
tcp::endpoint end_type;
tcp::acceptor acceptor(io_service, endpoint);
std::cout << "before accept" << endl;
acceptor.accept(*my_socket, end_type);
std::cout << "connected... hdl : " << my_socket->native_handle() << std::endl;
boost::asio::ip::address addr = end_type.address();
std::string sClientIp = addr.to_string();
std::cout << "\tclient IP : " << sClientIp << std::endl;
arr_thr[i] = boost::shared_ptr<boost::thread>(new boost::thread(&run, my_socket));
}
} catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
After you start the run
thread, the for loop in main starts again, destroying and reinitializing the local io_service
variable, the next event on the socket will still assume the old io_service object though, leading to your crash.
You should use only one instance of io_service
.
Also, you should have a look at the asynchronous functions which boost::asio provides, like async_accept
and async_read
, see for instance this example: http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/example/chat/chat_server.cpp
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