Если на компьютере установлено несколько сетевых карт, все они подключены к разным сетям и работают нормально, когда мы открываем сокет, как ОС определяет, какой сетевой адаптер использовать с этим сокетом? Позволяет ли API сокетов явно указывать NIC, который будет использоваться?
Как сокет знает, какой контроллер сетевого интерфейса использовать?
Ответ 1
Я не знаю, почему я был включен в предложение по редактированию, когда я даже не имел отношения к этому вопросу. У меня тоже было подобное предложение по редактированию и раньше... может быть какая-то ошибка/проблема.
(Если вы склонны голосовать "вверх", ответ @Shtéf заслуживает его больше, чем мой.)
Это зависит от того, подключаетесь вы или нет.
Если вы привязываете, вы можете привязать к определенному IP-адресу, соответствующему одному из интерфейсов машины, или вы можете привязать к 0.0.0.0, и в этом случае сокет будет прослушивать все интерфейсы.
Если вы подключите несвязанный сокет, то таблицы маршрутизации машины вместе с IP-адресом назначения будут определять, на каком интерфейсе будет отправлен запрос на подключение.
Можно связать сокет и подключить его. В этом случае сокет останется связанным согласно вызову связывания, когда это делает соединение. (Спасибо @RemyLebeau за указание на это.)
Ответ 2
Я пишу это с точки зрения Linux, но я полагаю, что это применимо повсюду.
Решение принимается при привязке сокета. Когда вызывается bind
, указанный вами адрес определяет интерфейс, который будет прослушивать сокет. (Или даже все интерфейсы.)
Даже если вы не используете bind
, это происходит неявно, когда вы connect
. Пункт назначения просматривается в таблице маршрутов, которая должна содержать маршрут к целевой сети. Маршрут также содержит интерфейс для использования и может дополнительно указать адрес источника. Если адрес источника не указан, выполняется первичный адрес интерфейса.
Фактически вы можете использовать bind
вместе с connect
, чтобы заставить исходящее соединение использовать определенный адрес и порт. Сокет должен всегда иметь эти два бита информации, поэтому даже если вы этого не сделаете, используется первичный адрес и выбран случайный порт.
Ответ 3
Я не уверен, какой метод является лучшим, но есть альтернативная теория для подхода bind() - before-connect(), который представил Штеф. Он должен использовать setsockopt() с SO_BINDTODEVICE. См.: http://codingrelic.geekhold.com/2009/10/code-snippet-sobindtodevice.html