I did the boost tutorial : An asynchronous TCP daytime server http://think-async.com/Asio/asio-1.1.1/doc/asio/tutorial/tutdaytime3.html When I want to test it, the server is running so that's good but if I do nc -C localhost 4242
the client got the message of the server but the client is directly disconnected after.
Here my code :
#include "server.h"
#include "connection.h"
Server::Server(boost::asio::io_service& io_service) : accept(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 4242))
{
wait_connection();
}
Server::~Server()
{
}
void Server::wait_connection()
{
std::cout << "wait_connection" << std::endl;
boost::shared_ptr<Connection> new_connection =
Connection::start_connection(accept.get_io_service());
accept.async_accept(new_connection->getSocket(), boost::bind(&Server::callback_accept, this, new_connection, boost::asio::placeholders::error));
}
void Server::callback_accept(boost::shared_ptr<Connection> new_connection, const boost::system::error_code &error)
{
if (!error)
{
new_connection->send_message_to_client();
wait_connection();
}
}
Connection::Connection(boost::asio::io_service& io_service) : socket(io_service)
{
}
Connection::~Connection()
{
std::cout << "destructeur Connection" << std::endl;
}
boost::shared_ptr<Connection> Connection::start_connection(boost::asio::io_service& io_service)
{
return (boost::shared_ptr<Connection>(new Connection(io_service)));
}
boost::asio::ip::tcp::socket& Connection::getSocket()
{
return (this->socket);
}
void Connection::send_message_to_client()
{
message = "Bienvenue!\n";
boost::asio::async_write(socket, boost::asio::buffer(message), boost::bind(&Connection::callback_send, shared_from_this()));
}
void Connection::callback_send()
{
}
int main()
{
try {
boost::asio::io_service io_service;
Server server(io_service);
io_service.run();
}
catch (std::exception& e) {
std::cerr << e.what() << std::endl;
}
return (0);
}
#ifndef SERVER_H
#define SERVER_H
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include "connection.h"
class Server {
private:
boost::asio::ip::tcp::acceptor accept;
public:
Server (boost::asio::io_service&);
~Server ();
void wait_connection();
void callback_accept(boost::shared_ptr<Connection> new_connection, const boost::system::error_code& error);
};
#endif /* end of include guard: SERVER_H */
#ifndef CONNECTION_H
#define CONNECTION_H
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
class Connection : public boost::enable_shared_from_this<Connection>
{
private:
boost::asio::ip::tcp::socket socket;
std::string message;
public:
Connection (boost::asio::io_service&);
~Connection ();
static boost::shared_ptr<Connection> start_connection(boost::asio::io_service&);
boost::asio::ip::tcp::socket& getSocket();
void send_message_to_client();
void callback_send();
};
#endif /* end of include guard: CONNECTION_H */
Crux: Shared pointers employ keep the object alive until the reference count reaches zero.
You write the message to the client here. When it's complete, you will execute callback_send
:
boost::asio::async_write(socket, boost::asio::buffer(message),
boost::bind(&Connection::callback_send, shared_from_this()));
So what do we do next?
void Connection::callback_send() {}
Oh. That's... not a lot. So. Nothing?
Well. Almost nothing .
It's a case of "not doing something is also doing something". By not posting another operation that keeps the socket/connection alive, this means that the connection is going to be released.
Because nothing else keeps the shared_ptr to the connection, shared_ptr will delete the connection (invoking the destructor, which you could see because it prints destructeur Connection
every time).
So. What is the solution? We Don't Know . It's up to you what you want to do after you said "welcome". In most likely-hood you will want to wait for some kind of message from the client. This would involve some async_read*
call which happily keeps the connection alive ( shared_from_this()
again).
Let's assume you want to keep receiving lines, and you send the same lines back, reversed:
void Connection::callback_send() {
boost::asio::async_read_until(socket, request, "\n",
boost::bind(&Connection::on_request_received, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void Connection::on_request_received(boost::system::error_code ec, size_t n) {
if (ec && !((ec == boost::asio::error::eof) && n))
std::cout << "Receive error: " << ec.message() << "\n";
else
{
std::cout << "Received request\n";
{
std::istream is(&request);
std::getline(is, message);
}
std::reverse(message.begin(), message.end());
std::cout << "Sending response: " << message << "\n";
message += '\n';
if (!ec) boost::asio::async_write(socket, boost::asio::buffer(message),
boost::bind(&Connection::callback_send, shared_from_this()));
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.