problème avec thread utilisant un functor (pour un server tcp avec boost asio)
Bonjour,
je compte faire un server tcp synchrone multi-thread en utilisant boost asio.
J'ai essayer d'adapter l'exemple simple de boost de l'echo server (http://www.boost.org/doc/libs/1_55_0...cho_server.cpp) en utilisant un functor et j'obtiens un comportement bizarre...
Je crée mon functor en l'initialisant avec la socket puis je le passe dans un thread et le detache.
Voici mon code:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
// g++ -std=c++11 -lboost_system -pthread blocking_echo_serv.cpp -o echo_serv
#include <cstdlib>
#include <iostream>
#include <thread>
#include <utility>
#include <boost/asio.hpp>
#include <atomic>
#include <vector>
using boost::asio::ip::tcp;
const int max_length = 1024;
class Session
{
public:
Session(tcp::socket *sock):
iSock(sock), iId(sIds)
{
sIds++;
std::cout << "Session[" << iId << "] created\n";
std::cout << "sIds: " << sIds << std::endl;
}
~Session()
{
delete iSock;
std::cout << "Session[" << iId << "] deleted\n";
}
tcp::socket *sock(){return iSock;}
void operator() (){
std::cout << "Session[" << iId << "] starting\n";
try
{
for (;;)
{
char data[max_length];
boost::system::error_code error;
size_t length = iSock->read_some(boost::asio::buffer(data), error);
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
boost::asio::write(*iSock, boost::asio::buffer(data, length));
}
}
catch (std::exception& e)
{
std::cerr << "Exception in thread: " << e.what() << "\n";
}
std::cout << "Session[" << iId << "] finished\n";
}
private:
tcp::socket *iSock;
int iId;
static std::atomic<int> sIds;
};
std::atomic<int> Session::sIds{0};
void server(boost::asio::io_service& io_service, unsigned short port)
{
std::vector<Session *> vSessions{};
tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
for (;;)
{
tcp::socket *sock = new tcp::socket(io_service);
a.accept(*sock);
Session *session = new Session(sock);
vSessions.push_back(session);
std::thread t(*session);
t.detach();
std::cout << "Thread detached\n";
}
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
std::cerr << "Usage: echo_serv <port>\n";
return 1;
}
try
{
boost::asio::io_service io_service;
server(io_service, std::atoi(argv[1]));
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
} |
Lorsque je lance un client (telnet ou http://www.boost.org/doc/libs/1_55_0...cho_client.cpp) voici l'output:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
$ ./echo_serv 1111
Session[0] created
sIds: 1
Session[0] starting
Session[0] deleted
Thread detached
Exception in thread: Socket operation on non-socket
Session[0] finished
Session[0] deleted
Exception: accept: Already open |
Les premières lignes sont le resultat d'un telnet, la dernière avec l'exception est quand j'en relance un deuxième.
Je ne comprends pas pourquoi mon Functor est supprimer avant/durant l'exécution dans le thread. Je ne comprends pas non plus pourquoi il est supprimé aussi à la fin.
Comment puis je faire pour initialiser un objet et ensuite lancer une de ses functions dans un thread? Ce n'est pas comme cela en utilisant un Functor?