C++ 连续调用boost::asio::read\u async:无数据回调
我是boost::asio的新手,目前正在尝试构建一个简单的服务器应用程序,监听TCP服务器。客户端和服务器代码都是从我在网上找到的一个示例中派生出来的(这很好用)。C++ 连续调用boost::asio::read\u async:无数据回调,c++,boost,boost-asio,C++,Boost,Boost Asio,我是boost::asio的新手,目前正在尝试构建一个简单的服务器应用程序,监听TCP服务器。客户端和服务器代码都是从我在网上找到的一个示例中派生出来的(这很好用)。 我自己的服务器在没有任何数据的情况下不断调用async_read回调。我已经搜索了几天了,但没有发现示例和代码之间的差异:( 所以希望任何人都能告诉我我做错了什么 以下是我的服务器应用程序代码: #define DMOD DebugIds::TEST #define DSUBID 0x0002 #define CLASSNAME
我自己的服务器在没有任何数据的情况下不断调用async_read回调。我已经搜索了几天了,但没有发现示例和代码之间的差异:(
所以希望任何人都能告诉我我做错了什么 以下是我的服务器应用程序代码:
#define DMOD DebugIds::TEST
#define DSUBID 0x0002
#define CLASSNAME "CLIENT_TEST"
#include <debug/dbg.h>
#include <memory>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
void doRead ( tcp::socket& socket )
{
std::vector<char> buffer (0,1024);
INF ("call async_read");
boost::asio::async_read (
socket,
boost::asio::buffer(buffer.data(), buffer.size() ),
[&socket](boost::system::error_code ec, std::size_t length)
{
INF ("async_read callback");
if (!ec )
{
INF ( "accept %d bytes of data from client", length );
}
else
{
ERR ( "cannot read from client" );
}
INF ("call doRead");
doRead ( socket );
}
);
}
int main(int argc, char* argv[])
{
bool startClient = true;
bool startServer = true;
Debug::Instance()->setModuleLevel ( DebugIds::TEST, INFO );
Debug::Instance()->setModuleLevel ( DebugIds::SERVER, DETAIL );
Debug::Instance()->setModuleLevel ( DebugIds::CLIENT, DETAIL );
if ( argc > 1 )
{
INF ( "argv[1]=%s", argv[1] );
if ( strcmp ("s", argv[1]) == 0 )
{
startClient = false;
}
else if ( strcmp ("c", argv[1]) == 0 )
{
startServer = false;
}
}
boost::thread serverThread;
boost::thread clientThread;
boost::mutex mutex;
boost::condition_variable clientcond;
unsigned int port = 12342;
std::string _port = "12342";
std::string adr = "127.0.0.1";
INF ( "startServer=%d startClient=%d", startServer, startClient );
INF ( "adr=%s port=%d _port=%s", adr.c_str(), port, _port.c_str() );
boost::asio::io_service io_service_server;
if ( startServer )
{
// start threads
mutex.lock();
INF ( "start server thread" );
serverThread = boost::thread (
[&]() //lambda method
{
try
{
INF ( "create TCP endpoint" );
boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string(adr), port );
//boost::asio::ip::tcp::endpoint ep(tcp::v4(), port );
INF ( "create TCP socket" );
tcp::socket m_socket(io_service_server);
INF ( "create TCP acceptor" );
tcp::acceptor m_acceptor(io_service_server,ep);
INF ( "call async_accept" );
m_acceptor.async_accept ( m_socket,
[&](boost::system::error_code ec)
{
INF ( "async_accept callback" );
if ( !ec )
{
INF ( "call doRead" );
doRead ( m_socket );
}
else
{
ERR ( "cannot accept client" );
}
}
);
INF ( "notify server is init" );
clientcond.notify_one();
INF ( "io_service_server.run()" );
io_service_server.run();
}
catch (std::exception& e)
{
ERR ( "Exception: %s", e.what() );
return (0);
}
INF ( "End server application" );
return (0);
});
}
boost::asio::io_service io_service_client;
if ( startClient )
{
clientThread = boost::thread (
//[&mutex,&adr,&_port,&spC,&io_service_client]()
[&]()
{
INF ( "wait for server to be initialized" );
boost::unique_lock<boost::mutex> lock(mutex);
clientcond.wait(lock);
INF ( "server initialization finished" );
try
{
tcp::resolver resolver(io_service_client);
auto endpoint_iterator = resolver.resolve({ adr, _port });
INF ( "create and init testclient" );
#if 0
uint8_t count = 0;
std::vector<char> v(0,256);
for ( auto c: v )
{
c = ++count;
}
spC->write(v.data(), v.size());
#endif
io_service_client.run();
}
catch (std::exception& e)
{
ERR ( "Exception: %s", e.what() );
}
INF ( "End client application" );
return (0);
});
}
char line[256];
while ( std::cin.getline(line, 256) )
{
INF ( "got %s", line );
if ( 0 == strcmp ("exit", line ) )
{
#if 0
if (spC)
{
spC->close();
io_service_client.stop();
if (spC) clientThread.join();
spC = std::shared_ptr<Client>();
}
if (spS)
{
spS->stop();
io_service_server.stop();
if (spC) serverThread.join();
spS = std::shared_ptr<Server>();
}
#endif
break;
}
}
#if 0
if (spC) clientThread.join();
if (spS) serverThread.join();
#endif
return (0);
}
为了完整性,我将添加我在I-Net中找到的示例代码(略有更改):
示例客户端:在数据从服务器到达之前,异步读取调用一直处于阻塞状态
//
// chat_client.cpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <cstdlib>
#include <deque>
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include "chat_message.hpp"
using boost::asio::ip::tcp;
#define DMOD DebugIds::TEST
#define DSUBID 0x0002
#define CLASSNAME "CLIENT_TEST"
#include <debug/dbg.h>
typedef std::deque<chat_message> chat_message_queue;
class chat_client
{
public:
chat_client ( boost::asio::io_service& io_service,
tcp::resolver::iterator endpoint_iterator)
: m_io_service(io_service),
m_socket(io_service)
{
INF ("");
do_connect ( endpoint_iterator );
}
void write ( const chat_message& msg )
{
INF ( "post io service" );
m_io_service.post(
[this, msg]()
{
bool write_in_progress = !m_write_msgs.empty();
m_write_msgs.push_back(msg);
if (!write_in_progress)
{
INF ( "call do_write" );
do_write();
}
});
}
void close()
{
INF ( "close socket async" );
m_io_service.post([this]() { INF ("close socket"); m_socket.close(); });
}
private:
void do_connect(tcp::resolver::iterator endpoint_iterator)
{
INF ( "async_connect" );
boost::asio::async_connect ( m_socket, endpoint_iterator,
[this](boost::system::error_code ec, tcp::resolver::iterator)
{
INF ( "on async_connect" );
if (!ec)
{
INF ( "do_read_header" );
do_read_header();
}
});
}
void do_read_header()
{
INF ( "call async_read" );
boost::asio::async_read ( m_socket,
boost::asio::buffer(m_read_msg.data(), chat_message::header_length),
[this](boost::system::error_code ec, std::size_t /*length*/)
{
INF ( "on async_read" );
if (!ec && m_read_msg.decode_header())
{
INF ( "call do_read_body" );
do_read_body();
}
else
{
ERR ( "connect failed" );
m_socket.close();
}
});
}
void do_read_body()
{
INF ( "call async_read" );
boost::asio::async_read(m_socket,
boost::asio::buffer(m_read_msg.body(), m_read_msg.body_length()),
[this](boost::system::error_code ec, std::size_t /*length*/)
{
INF ( "body: on async_read" );
if (!ec)
{
std::cout.write(m_read_msg.body(), m_read_msg.body_length());
std::cout << "\n";
INF ( "body: call do_read_header" );
do_read_header();
}
else
{
INF ( "body: read failed" );
m_socket.close();
}
});
}
void do_write()
{
INF ( "call async_write" );
boost::asio::async_write(m_socket,
boost::asio::buffer(m_write_msgs.front().data(),
m_write_msgs.front().length()),
[this] ( boost::system::error_code ec, std::size_t length )
{
INF ( "on async_write" );
if (!ec)
{
m_write_msgs.pop_front();
if (!m_write_msgs.empty())
{
INF ( "call do_write" );
do_write();
}
else
{
}
}
else
{
INF ( "async_write failed" );
m_socket.close();
}
});
}
private:
boost::asio::io_service& m_io_service;
tcp::socket m_socket;
chat_message m_read_msg;
chat_message_queue m_write_msgs;
};
int main(int argc, char* argv[])
{
Debug::Instance()->setModuleLevel ( DebugIds::TEST, INFO );
Debug::Instance()->setModuleLevel ( DebugIds::SERVER, DETAIL );
Debug::Instance()->setModuleLevel ( DebugIds::CLIENT, DETAIL );
try
{
if (argc != 3)
{
INF ( "Usage: chat_client <host> <port>" );
return(1);
}
INF ( "Create IO service" );
boost::asio::io_service io_service;
INF ( "Create TCP resolver" );
tcp::resolver resolver(io_service);
INF ( "Create endpoint iterator" );
auto endpoint_iterator = resolver.resolve({ argv[1], argv[2] });
INF ( "Create client" );
chat_client c(io_service, endpoint_iterator);
INF ( "Start thread that waits on io_service" );
std::thread t([&io_service](){ io_service.run(); });
// run io_service in an own thread, so we can still handle the
// incomming data from commandline
char line[chat_message::max_body_length + 1];
while ( std::cin.getline(line, chat_message::max_body_length + 1) )
{
chat_message msg;
msg.body_length(std::strlen(line));
std::memcpy(msg.body(), line, msg.body_length());
msg.encode_header();
INF ( "write message %s", msg.data() );
c.write(msg);
}
c.close();
INF ( "Waits on io_service" );
t.join();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return (0);
}
//
//chat_client.cpp
// ~~~~~~~~~~~~~~~
//
//版权所有(c)2003-2013 Christopher M.Kohlhoff(chris在Kohlhoff.com)
//
//根据Boost软件许可证1.0版发布。(参见随附的
//文件LICENSE_1_0.txt或复制到http://www.boost.org/LICENSE_1_0.txt)
//
#包括
#包括
#包括
#包括
#包括
#包括“chat_message.hpp”
使用boost::asio::ip::tcp;
#定义DMOD DebugIds::TEST
#定义DSUBID 0x0002
#定义类名“客户端测试”
#包括
typedef std::deque chat_message_队列;
类聊天室客户端
{
公众:
聊天室客户端(boost::asio::io_服务和io_服务,
tcp::resolver::迭代器端点(迭代器)
:m_io_服务(io_服务),
m_插座(io_服务)
{
INF(“”);
do_connect(端点迭代器);
}
无效写入(常量聊天信息和消息)
{
INF(“io后服务”);
m_io_service.post(
[这个,味精]()
{
bool write_in_progress=!m_write_msgs.empty();
m_write_msgs.推回(msg);
如果(!正在写入)
{
INF(“呼叫写入”);
你写什么;
}
});
}
无效关闭()
{
INF(“异步关闭套接字”);
m_io_service.post([this](){INF(“closesocket”);m_socket.close();});
}
私人:
void do_connect(tcp::解析器::迭代器端点\u迭代器)
{
INF(“异步连接”);
asio::异步连接(m_套接字、端点迭代器、,
[this](boost::system::error_code ec,tcp::resolver::iterator)
{
INF(“在异步连接上”);
如果(!ec)
{
INF(“读头”);
是否读取标题();
}
});
}
void do_read_header()
{
INF(“调用异步读取”);
boost::asio::异步读取(m_套接字,
boost::asio::buffer(m_read_msg.data(),chat_message::header_length),
[this](boost::system::error\u code ec,std::size\u t/*length*/)
{
INF(“异步读取时”);
如果(!ec&&m_read_msg.decode_header())
{
INF(“调用do_read_body”);
读你的身体吗;
}
其他的
{
错误(“连接失败”);
m_socket.close();
}
});
}
void do_read_body()
{
INF(“调用异步读取”);
boost::asio::异步读取(m_套接字,
boost::asio::buffer(m_read_msg.body(),m_read_msg.body_length()),
[this](boost::system::error\u code ec,std::size\u t/*length*/)
{
INF(“正文:异步读取时”);
如果(!ec)
{
std::cout.write(m_read_msg.body(),m_read_msg.body_length());
std::cout setModuleLevel(debugid::TEST,INFO);
Debug::Instance()->setModuleLevel(DebugIds::SERVER,详细信息);
Debug::Instance()->setModuleLevel(DebugIds::CLIENT,详细信息);
尝试
{
如果(argc!=3)
{
INF(“用法:聊天室客户端”);
申报表(1);
}
INF(“创建IO服务”);
boost::asio::io_服务io_服务;
INF(“创建TCP解析器”);
tcp::解析器解析器(io_服务);
INF(“创建端点迭代器”);
auto-endpoint_iterator=resolver.resolve({argv[1],argv[2]});
INF(“创建客户端”);
聊天客户端c(io_服务、端点迭代器);
INF(“启动等待io_服务的线程”);
线程t([&io_服务](){io_服务.run();});
//在自己的线程中运行io_服务,这样我们仍然可以处理
//从命令行输入数据
字符行[chat_message::max_body_length+1];
while(std::cin.getline(line,chat_message::max_body_length+1))
{
聊天信息;
消息正文长度(标准::strlen(行));
std::memcpy(msg.body(),line,msg.body_length());
msg.encode_头();
INF(“写入消息%s”,msg.data());
c、 写(msg);
}
c、 close();
INF(“等待io_服务”);
t、 join();
}
捕获(标准::异常&e)
{
std::cerr getId());
参与者->交付(msg);
}
}
}
私人:
std::设置m_参与者;
枚举{max_recent_msgs=100};
聊天、信息、队列、最近的MSG;
};
//----------------------------------------------------------------------
课堂聊天室
:公共聊天室参与者,
公共标准::enabl
//
// chat_client.cpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <cstdlib>
#include <deque>
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include "chat_message.hpp"
using boost::asio::ip::tcp;
#define DMOD DebugIds::TEST
#define DSUBID 0x0002
#define CLASSNAME "CLIENT_TEST"
#include <debug/dbg.h>
typedef std::deque<chat_message> chat_message_queue;
class chat_client
{
public:
chat_client ( boost::asio::io_service& io_service,
tcp::resolver::iterator endpoint_iterator)
: m_io_service(io_service),
m_socket(io_service)
{
INF ("");
do_connect ( endpoint_iterator );
}
void write ( const chat_message& msg )
{
INF ( "post io service" );
m_io_service.post(
[this, msg]()
{
bool write_in_progress = !m_write_msgs.empty();
m_write_msgs.push_back(msg);
if (!write_in_progress)
{
INF ( "call do_write" );
do_write();
}
});
}
void close()
{
INF ( "close socket async" );
m_io_service.post([this]() { INF ("close socket"); m_socket.close(); });
}
private:
void do_connect(tcp::resolver::iterator endpoint_iterator)
{
INF ( "async_connect" );
boost::asio::async_connect ( m_socket, endpoint_iterator,
[this](boost::system::error_code ec, tcp::resolver::iterator)
{
INF ( "on async_connect" );
if (!ec)
{
INF ( "do_read_header" );
do_read_header();
}
});
}
void do_read_header()
{
INF ( "call async_read" );
boost::asio::async_read ( m_socket,
boost::asio::buffer(m_read_msg.data(), chat_message::header_length),
[this](boost::system::error_code ec, std::size_t /*length*/)
{
INF ( "on async_read" );
if (!ec && m_read_msg.decode_header())
{
INF ( "call do_read_body" );
do_read_body();
}
else
{
ERR ( "connect failed" );
m_socket.close();
}
});
}
void do_read_body()
{
INF ( "call async_read" );
boost::asio::async_read(m_socket,
boost::asio::buffer(m_read_msg.body(), m_read_msg.body_length()),
[this](boost::system::error_code ec, std::size_t /*length*/)
{
INF ( "body: on async_read" );
if (!ec)
{
std::cout.write(m_read_msg.body(), m_read_msg.body_length());
std::cout << "\n";
INF ( "body: call do_read_header" );
do_read_header();
}
else
{
INF ( "body: read failed" );
m_socket.close();
}
});
}
void do_write()
{
INF ( "call async_write" );
boost::asio::async_write(m_socket,
boost::asio::buffer(m_write_msgs.front().data(),
m_write_msgs.front().length()),
[this] ( boost::system::error_code ec, std::size_t length )
{
INF ( "on async_write" );
if (!ec)
{
m_write_msgs.pop_front();
if (!m_write_msgs.empty())
{
INF ( "call do_write" );
do_write();
}
else
{
}
}
else
{
INF ( "async_write failed" );
m_socket.close();
}
});
}
private:
boost::asio::io_service& m_io_service;
tcp::socket m_socket;
chat_message m_read_msg;
chat_message_queue m_write_msgs;
};
int main(int argc, char* argv[])
{
Debug::Instance()->setModuleLevel ( DebugIds::TEST, INFO );
Debug::Instance()->setModuleLevel ( DebugIds::SERVER, DETAIL );
Debug::Instance()->setModuleLevel ( DebugIds::CLIENT, DETAIL );
try
{
if (argc != 3)
{
INF ( "Usage: chat_client <host> <port>" );
return(1);
}
INF ( "Create IO service" );
boost::asio::io_service io_service;
INF ( "Create TCP resolver" );
tcp::resolver resolver(io_service);
INF ( "Create endpoint iterator" );
auto endpoint_iterator = resolver.resolve({ argv[1], argv[2] });
INF ( "Create client" );
chat_client c(io_service, endpoint_iterator);
INF ( "Start thread that waits on io_service" );
std::thread t([&io_service](){ io_service.run(); });
// run io_service in an own thread, so we can still handle the
// incomming data from commandline
char line[chat_message::max_body_length + 1];
while ( std::cin.getline(line, chat_message::max_body_length + 1) )
{
chat_message msg;
msg.body_length(std::strlen(line));
std::memcpy(msg.body(), line, msg.body_length());
msg.encode_header();
INF ( "write message %s", msg.data() );
c.write(msg);
}
c.close();
INF ( "Waits on io_service" );
t.join();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return (0);
}
//
// chat_server.cpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <cstdlib>
#include <deque>
#include <iostream>
#include <list>
#include <memory>
#include <set>
#include <utility>
#include <boost/asio.hpp>
#include "chat_message.hpp"
#define DMOD DebugIds::TEST
#define DSUBID 0x0002
#define CLASSNAME "SERVER_TEST"
#include <debug/dbg.h>
using boost::asio::ip::tcp;
#define DBG(X) std::cout << __FUNCTION__ << X << __LINE__ << std::endl;
//----------------------------------------------------------------------
typedef std::deque<chat_message> chat_message_queue;
//----------------------------------------------------------------------
class chat_participant
{
public:
chat_participant() : m_id(++m_counter) {}
virtual ~chat_participant() {}
virtual void deliver(const chat_message& msg) = 0;
static unsigned int m_counter;
unsigned int m_id;
unsigned int getId(){return (m_id);}
};
unsigned int chat_participant::m_counter = 0;
typedef std::shared_ptr<chat_participant> chat_participant_ptr;
//----------------------------------------------------------------------
class chat_room
{
public:
void join(chat_participant_ptr participant)
{
m_participants.insert ( participant );
for ( auto msg: m_recent_msgs )
{
INF ( "send available messages to session id=%d", participant->getId() );
participant->deliver(msg);
}
}
void leave(chat_participant_ptr participant)
{
INF ( "session id=%d", participant->getId() );
m_participants.erase(participant);
}
void deliver(const chat_message& msg, unsigned int session_id )
{
INF ("deliver message to all participiants" );
m_recent_msgs.push_back(msg);
while (m_recent_msgs.size() > max_recent_msgs)
m_recent_msgs.pop_front();
for (auto participant: m_participants)
{
if( session_id != participant->getId() )
{
INF (" -> deliver message to p=%d", participant->getId() );
participant->deliver(msg);
}
}
}
private:
std::set<chat_participant_ptr> m_participants;
enum { max_recent_msgs = 100 };
chat_message_queue m_recent_msgs;
};
//----------------------------------------------------------------------
class chat_session
: public chat_participant,
public std::enable_shared_from_this<chat_session>
{
public:
chat_session(tcp::socket socket, chat_room& room)
: m_socket ( std::move(socket) ),
m_room ( room )
{
INF ( "id=%d", getId() );
}
void start()
{
INF ( "id=%d", getId() );
m_room.join ( shared_from_this() );
do_read_header();
}
void deliver(const chat_message& msg)
{
INF ( "id=%d", getId() );
bool write_in_progress = !m_write_msgs.empty();
m_write_msgs.push_back(msg);
if (!write_in_progress)
{
do_write();
}
}
private:
void do_read_header()
{
auto self(shared_from_this());
INF ( "id=%d call async_read", getId() );
boost::asio::async_read(m_socket,
boost::asio::buffer(m_read_msg.data(), chat_message::header_length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
INF ( "id=%d read callback!", getId() );
if (!ec )
{
INF ( "wait for next message to receive" );
do_read_header();
}
else
{
m_room.leave(shared_from_this());
}
});
}
void do_write()
{
/**
* auto self(shared_from_this()); in combination with the function pointer
* [this, self](boost::system::error_code ec, std::size_t length )
* ensures, that the chat_session is alive, as long as the asynchronous
* operation is ongoing
*/
auto self(shared_from_this());
INF ( "id=%d start async_write", getId() );
boost::asio::async_write(m_socket,
boost::asio::buffer(m_write_msgs.front().data(),
m_write_msgs.front().length()),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
INF ( "id=%d write callback", getId() );
if (!ec)
{
m_write_msgs.pop_front();
if (!m_write_msgs.empty())
{
INF ( "messages avaliable -> call do_write" );
do_write();
}
}
else
{
INF ( "error on async write" );
m_room.leave(shared_from_this());
}
});
}
tcp::socket m_socket;
chat_room& m_room;
chat_message m_read_msg;
chat_message_queue m_write_msgs;
};
//----------------------------------------------------------------------
class chat_server
{
public:
chat_server ( boost::asio::io_service& io_service,
const tcp::endpoint& endpoint)
: m_acceptor ( io_service, endpoint ),
m_socket ( io_service ),
m_room () // call for m_room is not explicitly necessary, but
// makes the code more readable
{
INF ( "port=%d", endpoint.port() );
do_accept();
}
private:
void do_accept()
{
INF (" called");
m_acceptor.async_accept ( m_socket,
[this](boost::system::error_code ec)
{
if (!ec)
{
// std::make_shared<T>(args)
// creates a shared pointer of T and provides the arguments to
// the new object!
INF ( " clients connection: start a new chat session" );
std::make_shared<chat_session> ( std::move ( m_socket ), m_room )->start();
// http://stackoverflow.com/questions/3413470/what-is-stdmove-and-when-should-it-be-used
// move allows to swap the ressources instead of copying them around!
}
INF ( "wait for the next client to connect" );
do_accept();
});
}
tcp::acceptor m_acceptor;
tcp::socket m_socket;
chat_room m_room;
};
//----------------------------------------------------------------------
int main(int argc, char* argv[])
{
Debug::Instance()->setModuleLevel ( DebugIds::TEST, INFO );
Debug::Instance()->setModuleLevel ( DebugIds::SERVER, DETAIL );
Debug::Instance()->setModuleLevel ( DebugIds::CLIENT, DETAIL );
try
{
if (argc < 2)
{
std::cerr << "Usage: chat_server <port> [<port> ...]\n";
return (1);
}
INF ( "argc=", argc );
INF ("define io_service");
boost::asio::io_service io_service;
std::list<chat_server> servers;
for (int i = 1; i < argc; ++i)
{
INF ("define endpoint");
tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[i]));
// create new chat_server by calling its constructor and add
// it to the list. emplace_back takes care off the correct
// constructor selection
INF ( "Start chat server at %s:%d", endpoint.address().to_string().c_str(), endpoint.port() );
servers.emplace_back(io_service, endpoint);
}
std::cout << "io_service.stopped()=" << io_service.stopped() << std::endl;
INF ("io_service.run()");
boost::system::error_code ec;
int size = io_service.run(ec);
INF ( "io_service.run() [%d] returned with %s", size, ec.message().c_str() );
}
catch (std::exception& e)
{
ERR("Exception: %s", e.what());
}
INF ( "End server application" );
return (0);
}
void do_read()
{
std::shared_ptr<std::vector<char>> buf = std::make_shared<std::vector<char>>(1024, 0);
m_socket.async_read_some
(
boost::asio::buffer(*buf, 1024),
// copy buf. The buffer will be destroyed
// only after leaving the lambda function
[buf](boost::system::error_code err, std::size_t length)
{
if(!err)
{
// use buf
}
else
{
// abort
}
do_read();
}
);
}