这是我的boost::asio
服务器
class Server: public boost::enable_shared_from_this<Server>, private boost::noncopyable{
private:
boost::asio::ip::tcp::acceptor _acceptor;
boost::asio::ip::tcp::socket _socket;
public:
explicit Server(boost::asio::io_service& ios, boost::asio::ip::tcp::endpoint& endpoint):_acceptor(ios, endpoint), _socket(ios){
}
void start(){
accept();
}
void accept(){
std::cout << "accepting " << std::endl;;
_acceptor.async_accept(_socket, boost::bind(&Server::handler, this, boost::asio::placeholders::error));
}
void handler(const boost::system::error_code &ec){
const std::string message = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello, world!";
if(!ec){
boost::asio::async_write(_socket, boost::asio::buffer(message), boost::bind(&Server::write_handler, this));
}else{
std::cout << ec << std::endl;
}
accept();
}
void write_handler(){
}
boost::asio::ip::tcp::socket& socket(){
return _socket;
}
};
int main(){
boost::asio::io_service ios;
const unsigned int port = 5050;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
Server server(ios, endpoint);
server.start();
ios.run();
return 0;
}
第一次以'Hallo World'回应;
然后它只是在accept
&lt; - &gt;中继续循环handler
循环并且不写欢迎消息。 ec
打印
asio.misc:1
accepting
asio.misc:1
accepting
asio.misc:1
accepting
asio.misc:1
accepting
asio.misc:1
accepting
asio.misc:1
accepting
......
永不停止
答案 0 :(得分:4)
无限循环是_socket
正在使用的结果。第一个async_accept()
有效,因为_socket
未使用。但是,_socket
永远不会关闭,因此async_accept()
与_socket
的额外调用将会失败。 async_accept()
的 peer 参数期望套接字未被使用,因为它将使用套接字进行新连接。这可以通过以下任一方式解决:
boost::shared_ptr
管理套接字。这允许服务器处理多个并发连接。_socket
中的write_handler
,然后调用accept()
。这会将服务器一次限制为一个连接。另外,请注意async_write()
。调用者保留底层缓冲区内存的所有权,调用者必须保证它在调用处理程序之前保持有效。在这种情况下,message
将在调用write_handler()
之前弹出堆栈。如果message
为const
,请考虑将其static
保证其持续时间。
在将对象传递给shared_from_this()
调用的实例时,请使用this
代替bind
。否则,this
指向的实例可能会被删除,因为只有在使用shared_from_this()
时才能正确引用计数。
最后,在打印boost::system::error_code
时,使用error_code.message()
方法获取更有意义的消息。在无限循环的情况下,它将打印“已经打开”。
以下是一次支持一个连接的修改后的handler()
和write_handler()
代码:
void accept(){
std::cout << "accepting " << std::endl;;
_acceptor.async_accept(_socket, boost::bind(&Server::handler, shared_from_this(), boost::asio::placeholders::error));
}
void handler(const boost::system::error_code &ec){
// Guarantee message will remain valid throughout the duration of async_write.
static const std::string message = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello, world!";
if(!ec){
// write_handler will accept the next connection once it is done with the socket.
boost::asio::async_write(_socket, boost::asio::buffer(message), boost::bind(&Server::write_handler, shared_from_this()));
}else{
std::cout << ec.message() << std::endl;
// Try accepting on error.
accept();
}
}
void write_handler(){
_socket.close();
// Now that the socket is closed, new connectiosn can be accepted.
accept();
}