2013-03-22 87 views
0

我有一个使用boost asio的简单客户端版本。一旦客户端发送数据,客户端就会收到服务器的响应。下面是客户端的代码客户端无法接收数据 - 客户端中的socket.async_receive异常

void RunClient() 
    { 
     try 
     { 
      boost::asio::io_service io_service; 
      boost::asio::ip::tcp::resolver resolver(io_service); 
      boost::asio::ip::tcp::resolver::query query("127.0.0.1", boost::lexical_cast<std::string>(7777)); //9100 
      boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); 
      boost::asio::ip::tcp::socket socket(io_service); 
      socket.async_receive(boost::asio::buffer(buf_client, 3000), 0, ClientReceiveEvent); 

      boost::asio::connect(socket, endpoint_iterator); 

      boost::system::error_code ignored_error; 
      std::cout << "Sending message \n"; 
      boost::asio::write(socket, boost::asio::buffer("Data to send"), ignored_error); 
      io_service.run(); 
     } 
     catch (std::exception & ex) 
     { 
      std::cout << "[" << boost::this_thread::get_id()<< "] Exception: " << ex.what() << std::endl; 
     } 
    } 

这里是我的ClientReceiveEvent

void ClientReceiveEvent(const boost::system::error_code& error, std::size_t bytes_transferred) 
    { 
     if(!error) 
     { 
      std::cout << "Message: " << buf_client.data() << std::endl; 

     } 
     else 
     { 
      std::cout << "Error occurred." << error.message() << std::endl; 
     } 
    } 

我得到一个错误从上面的方法进入数据

Error occurred.The file handle supplied is not valid 

任何建议,我在做什么客户端错误?

更新:

我得到的代码工作但我很困惑,为什么声明

socket->async_receive(boost::asio::buffer(buf_client, 3000), 0, ClientReceiveEvent); 

需要放置之后连接。以及为什么要发言

io_service->run(); 

需要放在最后。我认为这开始了异步过程。

我也想知道我将如何重新发送数据到服务器。我可以发送一次成功。我如何重新发送命令?

工作代码为:

boost::shared_ptr<boost::asio::io_service> io_service(new boost::asio::io_service); 
      boost::shared_ptr<boost::asio::ip::tcp::socket> socket( new boost::asio::ip::tcp::socket(*io_service)); 
      boost::asio::ip::tcp::resolver resolver(*io_service); 
      boost::asio::ip::tcp::resolver::query query("127.0.0.1", boost::lexical_cast<std::string>(7777)); //9100 
      boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); 
      socket->connect(endpoint_iterator->endpoint()); 
      socket->async_receive(boost::asio::buffer(buf_client, 3000), 0, ClientReceiveEvent); 
      boost::system::error_code ignored_error; 
      std::cout << "Sending message \n"; 
      boost::asio::write(*socket, boost::asio::buffer("some data"), ignored_error);   
      io_service->run(); 
+0

即使'async_receive'只会在你调用run()之后才会执行,它在调用'async_receive'时可能仍然需要一个连接的套接字。你有没有试过改变'connect'和'async_receive'的顺序? – dhavenith 2013-03-22 08:34:06

+0

刚刚更新了我的帖子。它仍然不起作用 – MistyD 2013-03-22 08:46:12

+0

你的代码在connect之前仍然调用'async_receive'。在内部,这可能(我猜在这里)将内部套接字句柄发送到套接字服务对象。如果我的猜测是正确的,那么同步写入应该成功,在此之后,async_receive应该失败。 – dhavenith 2013-03-22 09:06:50

回答

0

虽然async_receive时间表的读取动作的代码调用run()后,将执行,但它仍然在您所呼叫的async_receive功能本身现时需要连接的插座。这是因为在内部,async_receive实现如下:

this->get_service().async_receive(this->get_implementation(),buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); 

this->get_implementation()表达式返回内部套接字句柄的副本,因为它是当时,在您的案件无关。

换句话说,在安排了异步读取之后,它将无助于连接套接字,因为读取将在未连接的套接字上进行调度。

+0

目前,我的io_service-> run()被放置在发送消息之后。如果我想在此之后发送另一条消息怎么办? – MistyD 2013-03-22 09:46:48

+0

@MistyD,这取决于。如果第二次写入是对接收的反应,则只需在接收处理程序中调用(async_)写入(通常与async_receive一起使用,以继续对新传入数据作出反应)。这通常是如何使用asio构建服务的。 或者,如果将写入更改为异步写入,则可以在第一次写入的写入处理程序中执行第二次写入。 – dhavenith 2013-03-22 09:53:46

+0

如果不是,我想把它放在io_service-> run()之后? – MistyD 2013-03-22 09:56:41