2015-10-18 76 views
1

我目前正在使用Boost :: Asio来做一个基本的读/写服务器,在使用库的async_read函数时我有一个小问题。异步读取服务器BoostAsio没有调用处理程序

这里是我的代码片段:

main.cpp中

#include <ctime> 
#include <iostream> 
#include <string> 
#include <boost/asio.hpp> 
#include "TCPServer.hpp" 
#include "TCPConnection.hpp" 

using boost::asio::ip::tcp; 

int main() 
{ 
    try 
    { 
     boost::asio::io_service io_service; 
     TCPServer server(io_service); 
     io_service.run(); 
    } 
    catch (std::exception& e) 
    { 
     std::cerr << e.what() << std::endl; 
    } 

    return 0; 
} 

TCPServer.hpp:

#ifndef TCPSERVER_HPP_ 
#define TCPSERVER_HPP_ 

#include <ctime> 
#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 "TCPConnection.hpp" 

using boost::asio::ip::tcp; 

class TCPServer 
{ 
private: 
    tcp::acceptor _acceptor; 

public: 
    TCPServer(boost::asio::io_service& ioService) 
    : _acceptor(ioService, tcp::endpoint(tcp::v4(), 4040)) 
    { 
    startAccept(); 
    } 

private: 
    void startAccept() 
    { 
    TCPConnection::pointer newConnection = 
     TCPConnection::create(_acceptor.get_io_service()); 
    _acceptor.async_accept(newConnection->getSocket(), 
          boost::bind(&TCPServer::handleAccept, this, newConnection, 
             boost::asio::placeholders::error)); 
    } 

    void handleAccept(TCPConnection::pointer newConnection, const boost::system::error_code& error) 
    { 
    if (!error) 
     { 
     newConnection->asyncWrite("JIOLE"); 
     startAccept(); 
     } 
    } 
}; 

#endif 

TCPConnection.hpp:

#ifndef TCPCONNECTION_HPP_ 
#define TCPCONNECTION_HPP_ 

#include <ctime> 
#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 TCPConnection : public boost::enable_shared_from_this<TCPConnection> 
{ 
private: 
    boost::asio::ip::tcp::socket _socket; 
    std::string _readMessage; 
    boost::asio::streambuf _response; 

public: 
    typedef boost::shared_ptr<TCPConnection> pointer; 

    static pointer create(boost::asio::io_service& ios) 
    { 
    return pointer(new TCPConnection(ios)); 
    } 

    boost::asio::ip::tcp::socket& getSocket() 
    { 
    return _socket; 
    } 

    void asyncWrite(const std::string &message) 
    { 
    boost::asio::async_write(_socket, 
          boost::asio::buffer(message), 
          boost::bind(&TCPConnection::handleWrite, shared_from_this(), 


    boost::asio::placeholders::error)); 
     std::cout << "AsyncWrite" << std::endl; 
     } 

    void asyncRead() 
    { 
    std::cout << "1st \"asyncRead\"" << std::endl; 
    boost::asio::async_read(_socket, 
          _response, 
          boost::bind(&TCPConnection::handleRead, shared_from_this(), 
             boost::asio::placeholders::error)); 
    std::cout << "2nd \"asyncRead\"" << std::endl; 
    } 

    void close() 
    { 
    _socket.close(); 
    } 

private: 

    TCPConnection(boost::asio::io_service &ioS) : _socket(ioS) {} 

    void handleWrite(const boost::system::error_code& error) 
    { 
    std::cout << "Write Handler" << std::endl; 
    if (!error) 
     { 
     asyncRead(); 
     } 
    //SEE WHAT TO DO IN CASE OF ERROR                                             
    } 

    void handleRead(const boost::system::error_code& error) 
    { 
    std::cout << "Read Handler" << std::endl; 
    if (!error) 
     { 
     std::cout << &_response << std::endl; 
     asyncRead(); 
     } 
    else 
     { 
     std::cout << &error << std::endl; 
     _socket.close(); 
     } 
    //CREATE SENDER(RSEPONSE::ERROR)                                             
    } 

}; 

#endif 

问题是我的async_read不会调用处理程序。下面是输出:

输出:

AsyncWrite 
Write Handler 
1st "asyncRead" 
2nd "asyncRead" 

当我在写一个NetCat的客户不劳而获正在接收。

这里,当我按下Ctrl + C会发生什么:

Read Handler 
0x7fff645f3be0 

为什么没有得到任何我不明白。

回答

1

问题是你没有告诉async_read它应该调用处理函数。有两种方式可以指定:指定输入大小,之后应该调用处理程序或通过async_read_until指定分隔符。

在你的情况,你可以使用以下命令:

boost::asio::async_read_until(_socket, 
           _response, 
           "\n", 
           boost::bind(&TCPConnection::handleRead, 
              shared_from_this(), 
              boost::asio::placeholders::error) 
          ); 

这将调用时,一个新行从客户端发送的处理程序。

+0

非常感谢!这即刻起作用! –

+1

请注意,它可能会读取多于第一个分隔符('recv'以区块接收,并且可能有相同区块中的尾随数据)。此外,您可以通过传递一个仿函数来创建(更多)更高级的停止条件,以便您可以通过主动逻辑确定消息何时完成。 – sehe

+0

如果我可能再问你一件事@sehe,我收到了最后没有任何“\ n”的基本文本(而且我无法改变这个事实)例如:“你好”我怎么能知道何时停止阅读? –