C++ 如何使用带有Boost Asio插槽的特定网络接口/Ip?
我有一个Debian/linux服务器,它有几个Ip地址,都分配给同一个物理网卡。C++ 如何使用带有Boost Asio插槽的特定网络接口/Ip?,c++,linux,sockets,boost,boost-asio,C++,Linux,Sockets,Boost,Boost Asio,我有一个Debian/linux服务器,它有几个Ip地址,都分配给同一个物理网卡。/etc/network/interfaces配置文件如下所示(xx表示数字) 我正在开发一个客户端应用程序,它使用Boost Asio处理所有网络连接。在此应用程序中,我希望能够使用特定的networkinterface/Ip地址连接到外部服务器。我发现了类似的问题,但是简单地将一个boost::asio::ip::tcp::socket绑定到一个特定的端点,然后连接到一个外部服务器是行不通的。以下是我尝试的一个
/etc/network/interfaces
配置文件如下所示(xx表示数字)
我正在开发一个客户端应用程序,它使用Boost Asio处理所有网络连接。在此应用程序中,我希望能够使用特定的networkinterface/Ip地址连接到外部服务器。我发现了类似的问题,但是简单地将一个boost::asio::ip::tcp::socket
绑定到一个特定的端点,然后连接到一个外部服务器是行不通的。以下是我尝试的一个最简单的工作示例:
#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;
}
现在我有点迷路了,因为我不知道还能尝试什么。我不一定需要一个可移植的解决方案,任何使用Debian设置的东西都可以
更新
我将为一个适合我的设置的解决方案提供奖金。如有必要,我可以更改
/etc/network/interfaces
配置文件。但是,为了重用我的代码,任何解决方案都必须使用Boost Asio套接字(至少作为包装器)。通常,您可以使用以下工作流:
void connect_handler(const boost::system::error_code& error)
{
if (!error) { // Connect succeeded.
}
}
...
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::ip::tcp::endpoint remote_endpoint(
boost::asio::ip::address::from_string("1.2.3.4"), 12345); // server address
socket.open(boost::asio::ip::tcp::v4());
socket.bind(boost::asio::ip::tcp::endpoint(
boost::asio::ip::address::from_string("1.2.3.55"), // your local address
7777)
);
socket.async_connect(remote_endpoint, connect_handler);
可以找到更多信息。要绑定到特定接口,必须先打开连接。你做到了-到目前为止还不错。但在此之后,您将调用
boost::asio::connect(socket,remoteEndpoint)
将为您关闭连接(可以说是一项服务)
Boost告诉您它是这样做的,但您必须仔细观察。在“重载版本的connect
的参数”下的参考中,您使用的是
参数
要连接的插座。如果插座已经打开,它将关闭
或者在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;
}
(或在各自的远程端点上循环,如有必要,类似于boost源代码。)链接问题中的基本方法似乎是正确的,尽管(我在那里问过)我从未使用过
lower_layer()
函数,通常只是open()
和bind()
直接使用socket
对象的成员函数。@Chad那么open()->bind()->connect()
方法对您有效吗?我将在没有最底层的情况下测试它()
,但是我很难想象这就是问题所在(请参阅其他问题)。或者您是否碰巧有一个有效的代码示例?为什么要复制您的代码?无论如何,看看。open()
+bind()
似乎对我们有用。我主要处理接收端,通常是UDP多播
。对于TCP
,我们确保静态路由正确地设置在盒子上,但我知道如果我们bind()
到错误的接口,那么我们的TCP
连接将失败。@SteveVanOpstal,另一个问题是关于,为什么某些特定方法不起作用,而不是像这个问题那样,关于实现这一点的规范方法。但是我决定将它们合并到这个中,因为你是对的,另一个不再有意义了。我知道Boost Asio的例子,但我不知道它们如何回答我的问题…谢谢你的回答。也许我做错了什么,但这对我不起作用。我编辑了我的问题并添加了一个最小的代码示例。如果有什么问题,请告诉我。就这么简单!谢谢,我的问题与本文作者的问题完全相同,但有一个boost::asio::ip::udp::socket
。如果绑定并连接套接字,则无法通过绑定并连接的套接字接收数据。我没有检索到异常,尽管我想知道我做错了什么。我知道UDP是无连接的,但是为什么Boost.Asio API同时提供这两种方法呢?如果我阅读了提供的答案,我会认为使用bind和connect的方式应该是:1。绑定的套接字地址用于对[async]\u receive
的所有调用。2.连接的套接字地址用于对[async]\u send
的所有调用。因此,如果使用connect
,则无需使用receive\u from
和send\u to
方法。我错过什么了吗?顺便说一下,我正在使用Boost1.49.0。
void connect_handler(const boost::system::error_code& error)
{
if (!error) { // Connect succeeded.
}
}
...
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::ip::tcp::endpoint remote_endpoint(
boost::asio::ip::address::from_string("1.2.3.4"), 12345); // server address
socket.open(boost::asio::ip::tcp::v4());
socket.bind(boost::asio::ip::tcp::endpoint(
boost::asio::ip::address::from_string("1.2.3.55"), // your local address
7777)
);
socket.async_connect(remote_endpoint, connect_handler);
// 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;
}
socket.connect(*remoteEndpoint);