2013-03-22 88 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