我正在使用Boost-asio在Windows环境中的Java和C ++应用程序之间进行IPC。我现在正在C ++方面进行一些简单的测试,现在将数据写入“localhost”服务器中的端口100。这是我的代码:
int _tmain(int argc, _TCHAR* argv[])
{
boost::asio::io_service ioService;
TCPClient client(ioService, "localhost", "100");
ioService.run();
client.Write("Heloo!!!");
getchar();
}
TCPClient
课程:
#include <iostream>
#include <stdio.h>
#include <ostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
using namespace std;
using boost::asio::ip::tcp;
class TCPClient {
public:
// Constructor
TCPClient::TCPClient(boost::asio::io_service& IO_Service, const std::string& server, const std::string& port)
: resolver_(IO_Service), socket_(IO_Service){
connected = false;
// Query donde defino nombre del servidor y puerto
tcp::resolver::query query(server, port);
resolver_.async_resolve(query,
boost::bind(&TCPClient::handle_resolve, this,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
}
private:
tcp::resolver resolver_;
tcp::socket socket_;
bool connected;
public:
void Write(const std::string& data){
size_t s = 8;
boost::asio::async_write( socket_,
boost::asio::buffer(data, s),
boost::bind(&TCPClient::handle_write,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
std::cout << "async_write executed" << std::endl;
}
private:
// Resolucion de la direccion del servidor
void handle_resolve(const boost::system::error_code& err, tcp::resolver::iterator endpoint_iterator){
if (!err){
// Intentamos conectarnos al primer endpoint en la lista
tcp::endpoint endpoint = *endpoint_iterator;
socket_.async_connect( endpoint,
boost::bind(&TCPClient::handle_connect, this,
boost::asio::placeholders::error, ++endpoint_iterator));
}
else{
std::cout << "Error: " << err.message() << std::endl;
}
}
// Conexion al servidor
void handle_connect(const boost::system::error_code& err, tcp::resolver::iterator endpoint_iterator){
if (!err){
connected = true;
std::cout << "Connected" << std::endl;
}
else if (endpoint_iterator != tcp::resolver::iterator()){
// Conexion fallida, intentemos con el siguiente endpoint
socket_.close();
tcp::endpoint endpoint = *endpoint_iterator;
socket_.async_connect( endpoint,
boost::bind(&TCPClient::handle_connect, this,
boost::asio::placeholders::error, ++endpoint_iterator));
}
else{
std::cout << "Error: " << err.message() << std::endl;
}
}
void handle_write(const boost::system::error_code& error, std::size_t bytes_transferred){
if (!error){
std::cout << "Handle_write() sent bytes" << bytes_transferred << std::endl;
}
else {
std::cout << "Handle_write() error:" << error << std::endl;
}
}
};
所以我在Windows机器上使用端口侦听器,并成功设法连接到端口100:
但我没有收到数据Helloo!!
,因为您可以看到handle_connect()
未被调用。但是,当我关闭C ++应用程序时,数据被发送:
我错过了什么?我读了很多例子,我对这个库感到很困惑。
修改
好的,这是我的新主要代码:
int _tmain(int argc, _TCHAR* argv[])
{
boost::asio::io_service ioService;
TCPClient client(ioService, "localhost", "4000");
ioService.run();
client.Write("Heloo!!!");
ioService.reset();
ioService.run();
getchar();
}
我重新启动服务以便发送数据,现在我看到handle_write
正在调用,但在关闭应用程序之前我仍然无法看到传入的数据:
答案 0 :(得分:0)
简而言之,当io_service::run()
返回时,io_service
已失去工作。即使TCPClient::write()
向io_service
添加了更多工作,但io_service
的事件循环也不会再次被提供服务,从而导致永远不会调用TCPClient::handle_write()
。考虑一下:
io_service
,以便通过io_service::reset()
再次run()
,然后调用io_service::run()
。io_service
添加额外的工作或构建io_service::work
对象,重构程序以使io_service
永远不会失效。要更深入地了解io_service::run()
,请考虑阅读this回答。
此外,程序调用未定义的行为,因为它无法满足boost::asio::async_write()
的buffers
参数的生命周期要求:
[...]调用者保留了底层内存块的所有权,这必须保证它们在调用处理程序之前保持有效。
调用client.write("Heloo!!!")
时,会构造一个临时std::string
并传递给TCPClient::write()
。然后将临时string
用作buffers
的{{1}}参数。由于async_write()
不保证在调用TCPClient::write()
完成处理程序之前它不会返回,因此临时的生命周期违反了async_write()
的要求,导致未定义的行为。