gpt4 book ai didi

c++ - 停止异步连接

转载 作者:太空狗 更新时间:2023-10-29 21:41:55 26 4
gpt4 key购买 nike

我目前使用 Windows 7 64 位、MSVC2010 和 Boost.Asio 1.57。我想超时连接到 TCP 服务器。如果超时到期,我应该尽快关闭连接,因为 IP 地址(由用户选择)可能是错误的。

我知道我应该使用异步请求,因为同步请求不包含超时选项。所以我使用带有外部超时的 async_connect。这是我在很多地方找到的解决方案,包括 stackoverflow。

问题是下面的代码没有像我希望的那样运行。 async_connect 不会被 socket.close()“取消”。在我的电脑上,关闭套接字大约需要 15 秒才能完成,这使得我的程序有一段时间没有响应......我想要适当的超时(大约 3 秒)并在这段时间后关闭套接字,以便用户可以尝试连接另一个 IP 地址(从 HMI)

#include <iostream>
#include <boost\asio.hpp>
#include <boost\shared_ptr.hpp>
#include <boost\bind.hpp>

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

class tcp_client
{
public:
tcp_client(boost::asio::io_service& io_service, tcp::endpoint& endpoint, long long timeout = 3000000)
:m_io_service (io_service),
m_endpoint(endpoint),
m_timer(io_service),
m_timeout(timeout)
{
connect();
}

void stop()
{
m_socket->close();
}

private:

void connect()
{
m_socket.reset(new tcp::socket(m_io_service));

std::cout << "TCP Connection in progress" << std::endl;
m_socket->async_connect(m_endpoint,
boost::bind(&tcp_client::handle_connect, this,
m_socket,
boost::asio::placeholders::error)
);

m_timer.expires_from_now(boost::posix_time::microseconds(m_timeout));
m_timer.async_wait(boost::bind(&tcp_client::HandleWait, this, boost::asio::placeholders::error));
}

void handle_connect(boost::shared_ptr<tcp::socket> socket, const boost::system::error_code& error)
{
if (!error)
{
std::cout << "TCP Connection : connected !" << std::endl;
m_timer.expires_at(boost::posix_time::pos_infin); // Stop the timer !
// Read normally
}
else
{
std::cout << "TCP Connection failed" << std::endl;
}
}


public:
void HandleWait(const boost::system::error_code& error)
{
if (!error)
{
std::cout << "Connection not established..." << std::endl;
std::cout << "Trying to close socket..." << std::endl;
stop();
return;
}
}

boost::asio::io_service& m_io_service;
boost::shared_ptr<tcp::socket> m_socket;
tcp::endpoint m_endpoint;
boost::asio::deadline_timer m_timer;
long long m_timeout;
};

int main()
{
boost::asio::io_service io_service;
tcp::endpoint endpoint(boost::asio::ip::address_v4::from_string("192.168.10.74"), 7171); // invalid address
tcp_client tcpc(io_service, endpoint);

io_service.run();

system("pause");
}

我找到的唯一解决方案是在多个线程中运行 io_service:run(),并为每个连接创建一个新套接字。但是这个解决方案对我来说似乎无效,因为我必须指定多个线程,而且我不知道用户会在我的 HMI 中输入多少错误地址。是的,有些用户不如其他用户聪明......

我的代码有什么问题?如何以干净快速的方式中断 TCP 连接?

最好的问候,普基尔

最佳答案

代码没有任何基本错误,它完全符合您在我的 Linux 机器上的要求:

TCP Connection in progress
Connection not established...
Trying to close socket...
TCP Connection failed

real 0m3.003s
user 0m0.002s
sys 0m0.000s

注意事项:

  1. 您可能会成功地向 stop() 函数添加一个 cancel() 调用:

    void stop()
    {
    m_socket->cancel();
    m_socket->close();
    }
  2. 不过您应该检查超时是否中止:

    void HandleWait(const boost::system::error_code& error)
    {
    if (error && error != boost::asio::error::operation_aborted)
    {
    std::cout << "Connection not established..." << std::endl;
    std::cout << "Trying to close socket..." << std::endl;
    stop();
    return;
    }
    }

    否则在成功连接后隐式取消定时器仍然会关闭()套接字:)

  3. 如果您想并行运行(许多)连接尝试,您不需要更多的线程,甚至不需要一个以上的 io_service。这就是 Boost Asio 的本质:你可以在单个线程上进行异步 IO 操作。

关于c++ - 停止异步连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27688628/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com