Scenario Description
This example supports multi-threaded asynchronous processing of messages, for each link request, the creation of a thread to process the instructions later, Csimplesession::sessionthreadfunc is a thread function, Async_read_ The some function sets the callback function that receives the data continueread, in general, the Read_some function may not be able to read the packet sent by the client, of course, must specify a clear end flag, both parties must stipulate that when the reception is complete, must wait for the thread to return, Therefore, after the destructor calls the M_thread->join function, and so on the normal return of the thread function, close the connection, if there is no waiting for the thread to return, directly close the connection, will cause the Async_read_some function throws an exception, there is no clue at the moment
Service.h
#ifndef Qpidpushmessageservice_h
#define Qpidpushmessageservice_h
#include <iostream>
#include <vector>
#include <fstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function/function0.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/thread/mutex.hpp>
Namespace Qpid
{
Class Csimplesession:public Boost::enable_shared_from_this<csimplesession>
{
Public
Csimplesession (Boost::asio::io_service &io_service): M_socket (Io_service)
{
M_brunning = true;
Preparefornextrecv ();
}
~csimplesession ()
{
M_brunning = false;
M_thread->join ();
M_socket.close ();
}
void Startthread ()
{
Static Boost::asio::ip::tcp::no_delay option (TRUE);
m_socket.set_option (option);
M_thread.reset (New Boost::thread (Boost::bind (&csimplesession::sessionthreadfunc, this)));
}
void Sessionthreadfunc ()
{
while (m_brunning)
{
if (M_bstartsetcallbackread)
{
M_socket.async_read_some (Boost::asio::buffer (M_szrecvbuffer),
Boost::bind (&csimplesession::continueread, Shared_from_this (),
Boost::asio::p Laceholders::error,
Boost::asio::p laceholders::bytes_transferred));
M_bstartsetcallbackread = false;
}
Boost::this_thread::sleep_for (Boost::chrono::milliseconds (300));
}
M_brunning = false;
}
Boost::asio::ip::tcp::socket &getsocket ()
{
return m_socket;
}
BOOL Getcurthreadrunningstatus ()
{
return m_brunning;
}
void Preparefornextrecv ()
{
memset (M_szrecvbuffer, 0x00, 10240);
M_strmatch = "";
M_bstartsetcallbackread = true;
}
Private
void Continueread (const boost::system::error_code &error, std::size_t bytes_transferred)
{
if (Error)
{
M_brunning = false;
Return
}
M_strmatch = M_szrecvbuffer;
int nindexofcontentlength = M_strmatch.find ("content-length:", 0);
int indexofend = M_strmatch.find ("\r\n\r\n", 0);
if (nindexofcontentlength = =-1)
{
M_brunning = false;
Return
}
Std::cout << m_strmatch << Std::endl;
std::string Strcontextlen = m_strmatch.substr (nindexofcontentlength + indexofend-nindexofcontentlength-15);
int ncontextlen = atoi (Strcontextlen.c_str ());
if (Ncontextlen < M_strmatch.length ())
{
Handle
M_brunning = false;
Return
}
M_socket.async_read_some (Boost::asio::buffer (M_szrecvbuffer)),
Boost::bind (&csimplesession::continueread, Shared_from_this (),
Boost::asio::p Laceholders::error,
Boost::asio::p laceholders::bytes_transferred));
}
Private
Boost::asio::ip::tcp::socket M_socket;
Char m_szrecvbuffer[10240];
Std::string M_strmatch;
BOOL M_bstartsetcallbackread;
BOOL m_brunning;
Boost::shared_ptr<boost::thread> M_thread;
};
typedef boost::shared_ptr<csimplesession> Cptrsession;
Class Csimpleserver
{
Public
Csimpleserver (Boost::asio::io_service &io_service, Boost::asio::ip::tcp::endpoint &endpoint)
: M_ioservice (Io_service), M_acceptor (Io_service, endpoint)
{
Cptrsession newsession (New Csimplesession (Io_service));
M_vecsession.push_back (newsession);
M_acceptor.async_accept (Newsession->getsocket (),
Boost::bind (&csimpleserver::handleaccept,
This
NewSession,
Boost::asio::p laceholders::error));
}
void Handleaccept (cptrsession newsession, const boost::system::error_code &error)
{
if (error)return;
If the start function is blocked, the next processing connection is done only if the current connection is processed
Newsession->startthread ();
Clearhasendconnection ();
Cptrsession createnewsession (New Csimplesession (M_ioservice));
M_vecsession.push_back (createnewsession);
M_acceptor.async_accept (Createnewsession->getsocket (),
Boost::bind (&csimpleserver::handleaccept,
This
CreateNewSession,
Boost::asio::p laceholders::error));
}
void Clearhasendconnection ()
{
Std::vector<cptrsession>::iterator ITER;
iter = M_vecsession.begin ();
std::size_t count = M_vecsession.size ();
Std::cout << "Session Count:" << count << Std::endl;
while (iter! = M_vecsession.end ())
{
if (! ( *iter)->getcurthreadrunningstatus ())
{
Iter->reset ();
M_vecsession.erase (ITER);
Break
}
iter++;
}
}
void Run ()
{
M_ioservice.run ();
}
Private
Boost::asio::io_service &m_ioService;
Std::vector<cptrsession> m_vecsession;
Boost::asio::ip::tcp::acceptor M_acceptor;
};
void Startlistenthread ();
int Startlistenservice ();
}
#endif
Service.cpp
#include <boost/thread/thread.hpp>
#include "service.h"
void Qpid::startlistenthread ()
{
Boost::asio::io_service Ioservice;
Boost::asio::ip::tcp::endpoint Endpoint (boost::asio::ip::address::from_string ("192.168.0.34"), 7003);
Qpid::csimpleserver s (ioservice, endpoint);
S.run ();
}
int Qpid::startlistenservice ()
{
Boost::thread Servicethread (&startlistenthread);
Servicethread.detach ();
return 0;
}
Boost multithreading Asynchronous processing example