ASIO似乎是我项目中最好的异步跨平台网络库。但是,我无法让它实际连接。
首先,我没有使用Boost。我暂时在Windows上编译它,所以我不得不手动添加定义以告知ASIO我正在使用符合C ++ 11的编译器。
Source.cpp
#define TCPCLIENT_DEBUG
#include "TCPClient.hpp"
#include <iostream>
#define PORT "1234"
#define HOST "127.0.0.1"
int main() {
DEBUG("Starting program...\n");
namespace ip = asio::ip;
asio::io_service io;
ip::tcp::resolver::query query(HOST, PORT);
ip::tcp::resolver resolver(io);
decltype(resolver)::iterator ep_iter = resolver.resolve(query);
TCPClient client(io, ep_iter);
try {
std::cin.get();
}
catch (const std::exception &e) { // mainly to catch Ctrl+C
std::cout << e.what() << std::endl;
}
return 0;
}
TCPClient.hpp
#ifndef TCPCLIENT_HPP
#define TCPCLIENT_HPP
#include <functional>
#if defined(_DEBUG) || defined(TCPCLIENT_DEBUG)
#include <iostream>
#define DEBUG(dbg_msg) std::cerr << dbg_msg
#else
#define DEBUG(dbg_msg)
#endif
#define ASIO_STANDALONE
#define ASIO_HAS_CSTDINT
#define ASIO_HAS_STD_ARRAY
#define ASIO_HAS_STD_ADDRESSOF
#define ASIO_HAS_STD_SHARED_PTR
#define ASIO_HAS_STD_TYPE_TRAITS
#include <asio.hpp>
#ifndef BUFFER_SIZE
#define BUFFER_SIZE 1024
#endif
class TCPClient {
public:
TCPClient(asio::io_service& io, asio::ip::tcp::resolver::iterator endpoint_iter);
void on_connect(const asio::error_code& err);
private:
asio::io_service& m_io; // store the io service reference
asio::ip::tcp::socket m_sock; // object's socket
static const size_t bufSize{ BUFFER_SIZE }; // default buffer size
char m_buffer[bufSize]; // store the received data in a buffer
};
#endif//TCPCLIENT_HPP
TCPClient.cpp
#include "TCPClient.hpp"
TCPClient::TCPClient(asio::io_service& io, asio::ip::tcp::resolver::iterator endpoint_iter) : m_io{ io }, m_sock(io) {
asio::ip::tcp::endpoint endpoint = *endpoint_iter;
asio::error_code ec;
m_sock.async_connect(
endpoint,
std::bind(
&TCPClient::on_connect,
this,
std::placeholders::_1
)
);
}
void TCPClient::on_connect(const asio::error_code& err) {
DEBUG("Connected successfully!\n");
}
在我看来on_connect
从未被调用过。它只打印“正在启动程序......”。
使用netcat,我可以生成一个监听器,看到连接成功通过。
我的代码显然有什么问题?我现在只处理连接功能。
答案 0 :(得分:2)
通过调用async_connect
,您只注册一个异步操作。您应该在某处明确地调用io_service.run()
, - 可能在main
而不是std::cin.get()
, - 以使您的异步操作真正执行并调用回调。
在幕后,asio使用epoll
或类似的东西:它注册它感兴趣的事件(在你的情况下是套接字连接),然后等待事件发生。 io_service.run()
正是等待的地方。
我建议你看一些boost :: asio asyncronous教程,比如this one。
答案 1 :(得分:2)
处理程序仅在当前运行<item name="actionBarSize">@dimen/toolbar_height</item>
的线程中执行。由于永远不会运行io_service
,因此永远不会执行连接处理程序。要解决此问题,请致电io_service::run()
:
io_service
io_service
Using a timer asynchronously Tutorial注意到运行TCPClient client(io, ep_iter);
try {
io.run();
}
catch (const std::exception &e) {
std::cout << e.what() << std::endl;
}
:
最后,我们必须在
io_service
对象上调用io_service::run()
成员函数。asio库提供了一种保证,即只能从当前调用
io_service
的线程调用回调处理程序。因此,除非调用io_service::run()
函数,否则永远不会调用异步等待完成的回调。
io_service::run()
功能也将继续运行,同时还有“工作”要做。在这个例子中,工作是定时器的异步等待,所以在定时器到期并且回调完成之前,调用不会返回。重要的是要记住在致电
io_service::run()
之前给io_service
做一些工作。例如,如果我们忽略了对io_service::run()
的上述调用,则deadline_timer::async_wait()
将无法完成任何工作,因此io_service
将立即返回。