описание файла сокета - PullRequest
       1

описание файла сокета

1 голос
/ 23 февраля 2012

Так что я полностью потерял его, когда кто-то показал мне некоторый код, используя select (), например:

FD_ZERO(&readfds);
FD_SET(socket,&readfds);
FD_SET(0,&readfds);
.......// bind() and listen(),regular stuff
// Before select(),this guy cleared readfds to null and sort of start all over again
FD_ZERO(&readfds);// Behold,this is exactly the line confusing myself
FD_SET(socket,&readfds);
// select will be called in the future within a infinite loop 

То есть, говоря, что FD_ZERO после привязки и прослушивания по какой-то причине очищает предыдущее содержимое и снова вставляет дескриптор файла сокета в набор fd. Между тем, в наборе fd дескриптор 0 (стандартный ввод) явно исчез.

Может ли кто-нибудь объяснить все это? Я не чувствую, что это правильно, но я не могу понять это. Может быть, установка какого-то конкретного набора fd заново - это практичный механизм ...

Я думал, bind() и listen() могут каким-то образом изменить набор fd. Я установил пару точек разрыва и проверил выходные данные. Следовательно, набор fd не изменился вообще.

UPDATE:

Что меня действительно смущает, так это второй FD_ZERO(&readfds). Очевидно, что первое похоже на очистку буфера от ржавчины. На каждой итерации мы должны очистить fdset по умолчанию для будущего. Я просто не понимаю второй. Либо это не тот или не повредит в любом случае.

Ответы [ 3 ]

4 голосов
/ 23 февраля 2012

Не уверен, в чем ваша путаница, но вот объяснение.

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

Таким образом, fdset может быть чем-то вроде:

              Byte 0                              Byte 1
+---+---+---+---+---+---+---+---+ +---+---+----+----+----+----+----+----+
|fd0|fd1|fd2|fd3|fd4|fd5|fd6|fd7| |fd8|fd9|fd10|fd11|fd12|fd13|fd14|fd15|
+---+---+---+---+---+---+---+---+ +---+---+----+----+----+----+----+----+

Идея состоит в том, что вы устанавливаете бит для данного fd (дескриптор файла) если вам это интересно.Если вас это не интересует, оставьте бит чистым.

FD_ZERO удалит все биты, что является хорошей отправной точкой.Затем два вызова FD_SET установят биты для fd0 (стандартный ввод) и fd<socket>.

Затем вызов select, использующий этот fdset, вернется, если на стандартном вводе или действии было действиев сокете (действие типа будет зависеть от того, какую позицию параметра вы использовали при передаче fdset в select. Передача в качестве значения чтения fdset означает, что вы вернетесь, если вы сможете прочитать сокетили что-то обнаружилось при стандартном вводе (например, вы используете клавиатуру).

Это может быть полезно в коде для приложения "чат", так как оно будет ожидать ввода от вас или вашего другана другом конце.

Причина, по которой вам нужно обнулять и заново устанавливать биты в fdset, заключается в том, что select сам изменяет набор, чтобы указать, какой fd (или fds) обнаружил действиеon.

Пример: если что-то поступило через сокет и ничего не поступило через стандартный ввод, fdset изменился бы на select, чтобы установить только этот бит. Таким образом, вы можетеиспользуйте FD_ISSET, чтобы определить, на какие fds вы должны смотреть.


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

Без просмотра полного кода или документов архитектурного проекта:-) сложно сказать.

1 голос
/ 23 февраля 2012

Select() используется, когда вы пытаетесь прослушивать несколько сокетов одновременно. Каждый раз, когда вы 'принимаете () `соединение с сокетом, возвращается дескриптор сокета, и вы используете его для отправки / получения файлов.

Когда вы делаете FD_SET, вы добавляете дескриптор сокета в набор (это может быть чтение / запись). FD_ZERO очищает все записи из этого конкретного набора.

Таким образом, практически каждый раз, когда вы принимаете соединение, вы можете добавить дескриптор сокета к набору (то есть, если вы хотите использовать этот сокет для чтения / записи).

При вызове функции select() вы указываете набор, который хотите использовать. (Например, readfds) и select() опрашивает все сокеты, которые уже находятся в этом наборе (readfds).

Для получения дополнительной информации прочтите Руководство beej по сетевому программированию . Это очень хороший учебник для изучения.

0 голосов
/ 23 февраля 2012

select(2) изменяет наборы аргументов fd, поэтому вы должны повторно инициализировать их на каждой итерации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...