2016-06-27 2 views
0

Я новичок в программировании сокетов Linux. Здесь у меня есть основной вопрос:Linux UDP Socket: why select()?

для UDP, почему нам нужно select()?

  1. Как UDP является лицом без гражданства, поэтому сервер UDP просто обрабатывает все данные, он получил. Не будет нового сокета, созданного после того, как новый клиент отправит данные, не так ли?

  2. если да, то select() будет возвращен/уведомлен, как только этот сокет получит данные. Поэтому нам не нужно пропускать все, чтобы проверить, какой сокет уведомляется (поскольку будет только один сокет);

  3. Это правда? non-blocking UDP socket + select() == blocking UDP socket.

Спасибо!

ответ

4

Главное преимущество select() - это возможность дождаться ввода нескольких дескрипторов одновременно. Поэтому, когда у вас открыто несколько сокетов UDP, вы помещаете их в fd_set, вызываете select(), и он вернется, когда пакет будет получен по любому из них. И он возвращает fd_set, который указывает, какие из них имеют доступные данные. Вы также можете использовать его для ожидания данных из сети, также ожидая ввода с терминала пользователя. Или вы можете обрабатывать как UDP, так и TCP-соединения на одном сервере (например, DNS-серверы могут быть доступны с использованием TCP или UDP).

Если вы не используете select(), вам придется написать цикл, который непрерывно выполняет неблокирующее чтение на каждом сокете. Это не так эффективно, поскольку он будет тратить много времени на выполнение ненужных системных вызовов (представьте себе сервер, который получает только один запрос в день, но все время звонит recv() весь день).

Ваш вопрос, похоже, предполагает, что сервер может работать только с одним UDP-сокетом. Однако, если сервер имеет несколько IP-адресов, может потребоваться несколько сокетов. Клиенты UDP обычно ожидают ответа от того же IP-адреса, на который они отправили запрос. Стандартный API сокетов не предоставляет способ узнать, к какому IP-адресу был отправлен запрос, или установить исходный адрес исходящего ответа. Таким образом, общий способ реализовать это - открыть отдельный сокет, привязанный к каждому IP-адресу, и использовать select() или epoll(), чтобы ждать запроса на всех из них одновременно. Затем вы отправляете ответ через тот же сокет, в который был получен запрос, и он будет использовать связанный IP-адрес этого сокета в качестве источника.

(Linux имеет сокет расширения, которые делают это ненужным, см Setting the source IP for a UDP socket.)

+0

Таким образом, для вопроса # 3: Если я не использовать не блокирующий сокет, то мне просто нужно ждать сокета для данных , затем повторите, не так ли? Учитывая производительность для n UDP-клиентов -> 1 UDP-сервер, какой из них более эффективен (неблокирующий + select() или блокирующий сокет) на стороне UDP-сервера? –

+0

Если вы используете неблокирующий сокет, тогда, когда вы заблокированы на socket1, вы не можете обработать что-либо, полученное на socket2. Может быть, ваш вопрос действительно о том, почему вам понадобится более одного сокета UDP? – Barmar