2

通常、クライアントとしてどの送信元ポートからデータを送信するかは問題ではありませんが、テストのためにそれを実行したいと思います。そこで、クライアントのソケットを特定のポートにバインドしようとしましたが、ローカル マシンでクライアントとサーバーを実行している場合でも (宛先アドレスとして localhost を使用)、サーバーはソース ポートが 59000 のようなものであると通知します。ソケットを初期化しますこのような:

tcp::socket socket(io_service,tcp::endpoint(tcp::v4(),2000));

私が意図したことを行うことは可能ですか?メッセージがルーターを通過するときにルーターがポートを変更するかどうかを調べようとしています。それは、私が現在遊んでいるNATトラバーサルのものです。

4

1 に答える 1

6

ソケットを特定のポートにバインドすることは、質問に投稿されたとおりに行うことができます。

using boost::asio::ip::tcp;
boost::asio::io_service io_service;
tcp::socket socket(io_service, tcp::endpoint(tcp::v4(), 2000));
assert(socket.local_endpoint().port() == 2000); // true

この場合、socketオブジェクトが構築され、開かれ、アドレスとポートを持つローカルエンドポイントにバインドされます。INADDR_ANY2000

ローカル エンドポイントは、接続の確立方法の結果として変化している可能性があります。接続操作がsocket.connect()またはsocket.async_connect()メンバー関数のいずれかから開始されると、ソケットはリモート エンドポイントへの接続を試み、必要に応じてソケットを開きます。したがって、すでに開いているソケットで呼び出された場合、ソケットのローカル エンドポイントは変更されません。

一方、いずれかconnect()またはasync_connect()free 関数から接続操作が開始されると、エンドポイントへの接続を試行する前にソケットが閉じられます。したがって、ソケットは未指定のポートにバインドされます。フリー関数のドキュメントのパラメーター セクションでは、この動作が定義されています。

socket接続する。がすでに開いている場合は、socket閉じられます。

socket.close()さらに、およびメンバー関数がimplementationsocket.connect()内で次々に呼び出されるため、この動作を制御する明確な方法はありません。


上記の動作を示す完全な例を次に示します。

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

// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}

// Helper function used to initialize the client socket.
void force_endpoint(boost::asio::ip::tcp::socket& client_socket)
{
  using boost::asio::ip::tcp;
  client_socket.close();
  client_socket.open(tcp::v4());
  client_socket.bind(tcp::endpoint(tcp::v4(), 2000));
  std::cout << "client socket: " << client_socket.local_endpoint()
            << std::endl;
}

int main()
{
  using boost::asio::ip::tcp;
  boost::asio::io_service io_service;

  // Create all I/O objects.
  tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
  tcp::socket server_socket(io_service);
  tcp::socket client_socket(io_service);

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Initiate the connect operation directly on the socket.
  server_socket.close();
  force_endpoint(client_socket);
  acceptor.async_accept(server_socket, boost::bind(&noop));
  client_socket.async_connect(acceptor.local_endpoint(), boost::bind(&noop));

  // Print endpoints before and after running the operations.
  io_service.run();
  std::cout << "After socket.async_connect(): "
            << client_socket.local_endpoint() << std::endl;

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Initiate the connection operation with the free async_connect function.
  server_socket.close();
  force_endpoint(client_socket);
  acceptor.async_accept(server_socket, boost::bind(&noop));
  boost::asio::async_connect(
      client_socket,
      tcp::resolver(io_service).resolve(
        tcp::resolver::query("127.0.0.1", 
          boost::lexical_cast<std::string>(acceptor.local_endpoint().port()))),
      boost::bind(&noop));

  // Run the service, causing the client to connect to the acceptor.
  io_service.reset();
  io_service.run();
  std::cout << "After async_connect(): " 
            << client_socket.local_endpoint() << std::endl;
}

次の出力が生成されました。

client socket: 0.0.0.0:2000
After socket.async_connect(): 127.0.0.1:2000
client socket: 0.0.0.0:2000
After async_connect(): 127.0.0.1:53115
于 2014-05-20T15:07:22.880 に答える