gpt4 book ai didi

c++ - 如何将特定网络接口(interface)/Ip 与 Boost Asio 套接字一起使用?

转载 作者:IT王子 更新时间:2023-10-29 01:08:41 24 4
gpt4 key购买 nike

我有一个 Debian/linux 服务器,它有几个 Ip 地址,都分配给同一个物理网卡。 /etc/network/interfaces 配置文件如下所示(xx 代表数字)

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 176.xx.xx.144
netmask 255.255.255.0
network 176.xx.xx.0
broadcast 176.xx.xx.255
gateway 176.xx.xx.254

auto eth0:0
allow-hotplug eth0:0
iface eth0:0 inet static
address 46.xx.xx.57
netmask 255.255.255.255
broadcast 46.xx.xx.57

auto eth0:1
allow-hotplug eth0:1
iface eth0:1 inet static
address 94.xx.xx.166
netmask 255.255.255.255
broadcast 94.xx.xx.166

//IPv6 Stuff...

我正在开发一个使用 Boost Asio 处理所有网络连接的客户端应用程序。在此应用程序中,我希望能够使用特定的网络接口(interface)/IP 地址连接到外部服务器。我找到了 this类似的问题,但是简单地将 boost::asio::ip::tcp::socket 绑定(bind)到特定端点然后连接到外部服务器是行不通的。这是我尝试过的最小工作示例:

#include <iostream>
#include <boost/asio.hpp>

int main( int argC, char *argV[] ) {
boost::asio::io_service ioService;
boost::asio::ip::tcp::socket socket(ioService);

boost::asio::ip::tcp::endpoint localEndpoint(
boost::asio::ip::address::from_string("94.xx.xx.166"), 0);

boost::asio::ip::tcp::resolver resolver(ioService);
boost::asio::ip::tcp::resolver::iterator remoteEndpoint =
resolver.resolve(boost::asio::ip::tcp::resolver::query("haatschii.de", "80"));

socket.open(boost::asio::ip::tcp::v4());

std::cout << "Before binding socket has local endpoint: "
<< socket.local_endpoint().address().to_string()
<< ":" << socket.local_endpoint().port() << std::endl;

socket.bind(localEndpoint);

std::cout << "Before connecting socket has local endpoint: "
<< socket.local_endpoint().address().to_string()
<< ":" << socket.local_endpoint().port() << std::endl;

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

std::cout << "After connecting socket has local endpoint: "
<< socket.local_endpoint().address().to_string()
<< ":" << socket.local_endpoint().port() << std::endl;

//Test request to a page that echos our IP address.
boost::asio::write(socket,
boost::asio::buffer("GET /ip.php HTTP/1.1\r\nHost: haatschii.de\r\nAccept: */*\r\n\r\n", 57));

//Parse server response (not important for this code example)
return 0;
}

当我在我的服务器上运行它时,我得到:

Before binding socket has local endpoint: 0.0.0.0:0
Before connecting socket has local endpoint: 94.xx.xx.166:38399
After connecting socket has local endpoint: 176.xx.xx.144:45959
External server says we are using IP: 176.xx.xx.144

现在我有点迷茫,因为我不知道还能尝试什么。我不一定需要一个可移植的解决方案,任何适用于这个 Debian 设置的东西都可以。

更新

我将为适用于我的设置的解决方案悬赏。如有必要,我可以更改 /etc/network/interfaces 配置文件。然而,为了重用我的代码,任何解决方案都必须使用 Boost Asio 套接字(至少作为包装器)。

最佳答案

要绑定(bind)到特定接口(interface),您必须先打开连接。你这样做 - 到目前为止一切顺利。但在那之后你调用 boost::asio::connect(socket, remoteEndpoint); 它将为你关闭连接(可以说是一种服务)。

Boost 告诉您它确实如此 - 但您必须仔细观察。在您正在使用的 connect 的重载版本的参数下的引用中,它会说

Parameters

s

The socket to be connected. If the socket is already open, it will be closed.

或者在 boost/asio/impl/connect.hpp 中的实现:

// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

[...]

template <typename Protocol, typename SocketService,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol, SocketService>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
boost::system::error_code& ec)
{
ec = boost::system::error_code();

for (Iterator iter = begin; iter != end; ++iter)
{
iter = connect_condition(ec, iter);
if (iter != end)
{
s.close(ec);
s.connect(*iter, ec);
if (!ec)
return iter;
}
}

if (!ec)
ec = boost::asio::error::not_found;

return end;
}

(注意 s.close(ec);)


解决方案

应该很简单。将 boost::asio::connect... 替换为

socket.connect(*remoteEndpoint);

(或在相应的远程端点上循环,如有必要,类似于 boost 源代码。)

关于c++ - 如何将特定网络接口(interface)/Ip 与 Boost Asio 套接字一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20890703/

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