#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class session
{
public:
session(boost::asio::io_service& io_service)
: socket_(io_service)
{
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
socket_.async_read_some(boost::asio::buffer(data_, max_length - 1),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
data_[bytes_transferred] = '\0';
if(NULL != strstr(data_, "quit"))
{
this->socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both);
this->socket().close(); // how to make this dispatch "handle_read()" with a "disconnected" flag?
}
else
{
boost::asio::async_write(socket_,
boost::asio::buffer(data_, bytes_transferred),
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error));
socket_.async_read_some(boost::asio::buffer(data_, max_length - 1),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}
else
{
delete this;
}
}
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
//
}
else
{
delete this;
}
}
private:
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class server
{
public:
server(boost::asio::io_service& io_service, short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
session* new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
void handle_accept(session* new_session,
const boost::system::error_code& error)
{
if (!error)
{
new_session->start();
new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
else
{
delete new_session;
}
}
private:
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}
boost::asio::io_service io_service;
using namespace std; // For atoi.
server s(io_service, atoi(argv[1]));
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
在試驗boost :: asio時,我注意到在調用async_write()/ async_read_some()的過程中,有一個C++「new」關鍵字的用法。boost :: asio是否會產生過多的小堆分配,還是我錯了?
此外,當用一個發送例如100,000次數據的客戶端(1個連接)強調這個回顯服務器時,這個程序的內存使用率越來越高。
發生了什麼事?它會爲每次通話分配內存嗎?或者我錯了?詢問是因爲服務器應用程序分配不太合適,任何事情。我可以使用內存池來處理它嗎?
另一側問題:
參見 「這 - >插座()關閉();」 ?
我希望它最後一次發送相同的函數,並且發生斷開連接錯誤。需要做一些清理工作。我怎麼做?
謝謝各位大師(:
shared_from_this是來自shared_ptr的類,它爲您提供了一個指向自己的弱指針。當你創建一個應該被共享指針使用的類,並且你想從它自己獲得一個shared_ptr的時候,你可以從這個類中派生出來。有關說明,請參閱http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/sp_techniques.html#from_this。 – Christopher 2010-05-27 17:29:43
make處理程序代碼似乎創建了一個由綁定調用創建的函數對象的包裝。處理程序對象被複制,分配器通過引用傳遞。所有operator()(..)調用都被轉發給handler_對象。 alloc/free調用通過對allocator_的引用來處理。 – Christopher 2010-05-27 17:37:29
嗨克里斯托弗,謝謝你花時間回答!我不能說我真的瞭解你,但底線是我怎樣才能讓它在運行時不使用'新'操作符?一個簡單的例子,可能使用:: std :: vector來合併對象將會非常糟糕! – Poni 2010-05-30 07:11:07