pythonアプリケーションを実行しているターゲットマシンでは、3つのネットワークインターフェイスを使用できます。通常、3つのネットワークはすべて大きく異なりますが、3つのうち2つが同様のネットワーク上にある可能性があります。 。
以下の例では、ETH 2の宛先アドレスを制御できないため(事前構成されたシステムであるため)、プログラムで使用するアダプターを選択する必要がありました。
これは、OSが接続のルーティングでどのように機能するかに当てはまると確信しています。このアプリケーションはLinuxマシンだけでなくWindows7でも実行する必要がある可能性があるため、Pythonを使用して問題を解決するプラットフォームに依存しない方法があることを願っています。
サンプルコード
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.0.2', 8000)) # Which device will this connect to??
通常の場合
考えられるトラブルケース
追加情報
アダプターETH0、1、および2はすべて異なる物理ネットワークに接続されています
Windowsでは、使用するインターフェイスのIPアドレスがわかっている場合は、接続する前にそれにバインドするだけです。 Linuxでは、JimBが提案するソケットオプションSO_BINDTODEVICEを使用します(特権呼び出しでもあるようです)。
つまり、Windowsの場合
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.0.1', 0))
s.connect(('...'))
Windowsで送信元アドレスをバインドすると、そのIPアドレスのルーティングメトリックコストが高い場合でも、そのデバイスと同じIPアドレスを持つインターフェイスが選択されます。ただし、これはLinuxでは機能しません。これは、送信元アドレスを選択したデバイスのIPアドレスで常に上書きするためです。ルーティングは、宛先アドレスのみに基づいて行われます。唯一の例外は、送信元アドレスを127.0.0.1に設定した場合、Linuxはこれらのパケットがそのボックスから出て行くのを防ぎます。
Windowsについてはあまり話せませんが、Linuxでは通常、ルーティングの決定が行われるまでインターフェイスは選択されないため、通常、パケットがどのインターフェイスを離れるかについてはわかりません。
ただし、LinuxでSO_BINDTODEVICE
(man 7 socket
を参照)を使用するオプションがあります。これにより、ソケットがデバイスにバインドされますが、このオプションをソケットに設定できるのはrootのみです。
チェックしたところ、pythonソケットライブラリにはSO_BINDTODEVICE
が定義されていませんが、socket.h
から取得します。
# from socket.h
# define SO_BINDTODEVICE 25
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, 25, 'eth0')
参照: