Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用带有Boost Asio插槽的特定网络接口/Ip?_C++_Linux_Sockets_Boost_Boost Asio - Fatal编程技术网

C++ 如何使用带有Boost Asio插槽的特定网络接口/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绑定到一个特定的端点,然后连接到一个外部服务器是行不通的。以下是我尝试的一个

我有一个Debian/linux服务器,它有几个Ip地址,都分配给同一个物理网卡。
/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);