Перейти к содержанию

Вопрос по unix domain sockets


Гость

Рекомендуемые сообщения

Народ, кто-нибудь работал с unix domain socket?

Создаю локальный сокет (AF_LOCAL,SOCK_STREAM,0), делаю bind, listen. Вижу созданый файл сокета, и netstat тоже его показывает и говорит, что он STREAM и LISTENING. Далее добавляю его в FD_SET, делаю select(...). По срабатыванию select() на чтение, проверяю наличие этого сокета, делаю accept... и тут он мне выдает ошибку 11 (EWOULDBLOCK, она же EAGAIN, она же "Resource temporarily unavailable"). Клиентская прога говорит, что сконектилась, а сервер непрерывно сыпет эту ошибку... В чем я ошибся? С inet сокетами тоже самое проходит без проблем. Я уже думал, что локальные сокеты нельзя делать типа STREAM, но bind и listen проходят без ошибок, да и другие программы их применяют (напр. gpm). Доки об этом умалчивают (man socket и info libc). Делал сокет как nonblocking, так и без этого.

Кто знает, помогите, пожалуйста.

Ссылка на комментарий
Поделиться на другие сайты

не помешал бы кусочек кода...

0. Конечно можно делать STREAM

1. именно accept() возвращает EWOULDBLOCK?

2. Что значит "непрерывно сыпет ошибку"? на каждый коннект? или действительно "непрерывно"? в каком цикле? кода кусочек дай..

3. EWOULDBLOCK может вернуться только для неблокируещего сокета... в случае без NBLOCK программа должна аблокироваться в accept()...

4. последовательность fd = listen(); select(fd...); if (fd is readable) fd1= accept(fd...) НЕ ГАРАНТИРУЕТ, вообще говоря, что ты не заблокируешься в accept() (так как клиет мог закрыть сединение между select() и accept() и разные unix-ы в этом случае ведут себя по-разному)... поэтому если используешь select() для того чтобы узнать, что соединение готово для accept(), то всегда надо делать неблокирующий listen сокет... это к слову....

не видя кода, можно только предположить, что клиент "умирает" сразу после connect, т.е. пока сервер находится между select() и accept()...

=ipv4

Ссылка на комментарий
Поделиться на другие сайты

Благодарю за участие, но с проблемой я разобрался: как всегда - невнимательность - при копировании схожих блоков программы остлось не исправленное имя переменной... ж)

http://linux.ru.net/index.php?module=forums&faction=show&message=31007

Ссылка на комментарий
Поделиться на другие сайты

Добавлю к выше сказаному:

такой эффект (клиент коннектится и думает что все в порядке, а сервер на каждый accept() выдает ошибку в цикле while(select(.)) и тратит много процессорного времени) получается если в accept() передавать не существующий или не активный не блокируемый сокет. Даже если клиет закроет соединение, то select() продолжает генерить событие чтения для listen сокета (в Linux) и таких событий у меня было по 5-20 тыс. в секунду...

Ссылка на комментарий
Поделиться на другие сайты

> Добавлю к выше сказаному:

> такой эффект (клиент коннектится и думает что все в порядке,

> а сервер на каждый accept() выдает ошибку в цикле

> while(select(.)) и тратит много процессорного времени)

> получается если в accept() передавать не существующий или не

> активный не блокируемый сокет.

что == не вызывать accept вообще, не так ли?

>Даже если клиет закроет

> соединение, то select() продолжает генерить событие чтения

> для listen сокета (в Linux)

в любом unix. select() немедленно возвращается если есть ready сокеты, а они есть раз ты не вызывал accept().

тут нет никакой ошибки в линуксе, или "эффекта", ни даже чего-то недокументированного, либо "недоописанного" либо специфичного для линукса, как нет и в том, что клиент "думает, что все в порядке". все и есть в порядке! сокет становится ready ПОСЛЕ того как соединение tcp установлено (т.е. ПОСЛЕ syn, syn_ack, ack). accept() ничего не "акцептует" Smile

=ipv4

=ipv4

Ссылка на комментарий
Поделиться на другие сайты

После вызова connect() клиенту сразу возвращается управление (т.е., практически, соединение установлено на уровне TCP, но логически, программа сервер канал еще не создала). А в accept() я по ошибке пердавал номер другого listen сокета, на что получал -1. Подобной ошибки не ожидал и вся обработка сводилась к выводу сообщения об ошибке, а потом к началу цикла, к select(). А там по новой... В целом, забавно получилось ж)

Судя по всему, в libc (или glibc) делается буферизация событий, и даже когда клиент зактыл свой сокет, на серверной стороне остались события конекта (на listen сокете) и EOF (на еще не подтвержденном, не существующем сокете)...

Ссылка на комментарий
Поделиться на другие сайты

нет никакой "буфферезации собыий"... нету ее... пока ты не сделаешь accept, raedable listem socket остается readable вечно... единственный способ его сделать не readable это "прочитать", т.е. accept-овать... состояние клиента не имеет отношения к его readbility... в линуксе... в BSD если клиент сделает close() до того как ты сделаешь accept() (как в твоем случае из-за ошибки и происходит), то socket перестанет быть readable, если на нем без accept еще раз в select уснуть... но это приводит к тому, что есть шанс уснуть в accept() даже после select!... и это значит что надо использовать O_NBLOCK итд итп... в линукс (как и в SVR4) сокет остается readble пока его не accept-уешь, и accept() вернет ошибку, если между select и accept клиент успел сделать close()

=ipv4

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
×
×
  • Создать...