| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Программирование под Unix/Linux > Как проверить закрыт ли сокет |
| Автор: Zerstroer 12.8.2015, 14:22 | ||||
| Здравствуйте. Знаю, что вопрос относительно тривиальный, но обращаюсь за помощью и что бы разобраться в ситуации. Пишу под Linux. Работаю с сокетами. Использую "чистый" C. Создаю сокет:
Благополучно соединяюсь с ним, работаю, по завершению работы или при возникновении ошибок делаю его close(sock_descr). Далее, в зависимости от ситуации, мне нужно повторно использовать sock_descr. Либо повторно им воспользоваться, если я не делал ранее его close, либо заново сделать connect и пользоваться им. Вопрос заключается в следующем: как в определенном месте однозначно надежно (и по возможности просто) выяснить, что этот дескриптор сокета был ранее closed? Решение этого вопроса гуглил, но в ходу не совсем очевидные мне методы выяснения статуса сокета. Рекомендуют использовать read/write, но у меня вызывает сомнение использование этого метода. Адекватный ли вариант "мануально" контролировать статус сокета посредством использования рукописной структуры? Пример:
Заранее спасибо. |
| Автор: Zerstroer 12.8.2015, 19:47 |
| Перечитал свой первый пост, достаточно запутанно описал ситуацию. По сути, в случае ошибки, мне нужно делать полное переподключение и я использую один и тот же дескриптор сокета. Как выходить из этой ситуации? Вручную присваивать дескриптору после close значение -1? Как в таком случае открывать этот дескриптор повторно? |
| Автор: Alexeis 12.8.2015, 19:50 | ||
ООП наш лучший друг в слежении за ресурсами. |
| Автор: feodorv 12.8.2015, 20:07 | ||
В случае какой ошибки? Ошибки бывают слишком разные.
Зачем? В чем причина необходимости для использования того же дескриптора сокета? Почему бы просто не закрыть сокет, а потом его по-новой открыть в случае переподключения? У Вас им удерживается свой IP:port? |
| Автор: Zerstroer 12.8.2015, 20:29 |
| Alexeis, ООП использовать не могу - "чистый" Си. feodorv, по поводу ошибок. Имеются ввиду ошибки при подключении или при обмене данными (хост недоступен, порт занят, сервер не возвращает данные). В каждом из этих случаев мне необходимо осуществить несколько попыток повторного подключения. Я принял во внимание ваши советы, пересмотрел код. Вопросы стали еще проще и еще банальнее: 1. Фактически close не изменяет значение дескриптора сокета, а лишь закрывает его. Верно? Т.е. после close я могу присвоить переменной в которой ранее хранился действующий дескриптор сокета отрицательное значение для индикации того, что сокет закрыт? 2. Дескриптор действующего сокета не может быть отрицательным. Может ли дескриптор сокета быть равным 0? |
| Автор: feodorv 12.8.2015, 21:03 | ||
По сути верно, по форме я бы иначе сказал. Дело в том, что переменная сокета хранит дескриптор сокета, и при close данный дескриптор высвобождается и более ничему не соответствует (ни файлу, ни сокету), хотя переменная сокета продолжает хранить значение этого уже освобождённого дескриптора. Чтобы она этого не делала, и для индикации закрытости сокета, стОит присвоить переменной сокета отрицательное значение (обычно используют -1). Не может. Более того, отрицательное значение, возвращаемое вызовом socket(), сигнализирует об ошибке. Вообще, значения дескрипторов 0, 1 и 2 отведены под stdin, stdout и stderr. Если их последовательно закрыть, а затем сделать вызов socket(), то вполне возможно получить нулевое значение дескриптора сокета. По крайней мере, так было в Юниксах лет 10 назад, к сожалению, меня с тех пор от них оторвали, я не в курсе последних тенденций в этом направлении. Но учитывая значительный консерватизм в разработке Юниксов, не думаю, что здесь что-то изменилось. Можно, кстати, поставить эксперимент. Но в любом случае по стандарту нужно быть готовым к тому, что значение дескриптора сокета может быть нулём))) |
| Автор: Zerstroer 12.8.2015, 21:14 |
| feodorv, большое спасибо! Вы все объяснили до очевидного понятно. Ответы на все сформулированные вопросы я получил. Тему закрою если не возникнет дополнительных вопросов при исправлении взаимодействия с сокетами в коде. |
| Автор: Zerstroer 13.8.2015, 12:20 |
| Помечаю вопрос как решенный. Воспользовался советами feodorv. |
| Автор: svlary 17.8.2015, 14:33 |
Там есть одна заморочка, с которой я столкнулся на практике... Описываю ситуацию
Было у меня это очень давно и потому "помню туманно" Но там как-то надо использовать опцию сокета SO_REUSEBLE_ADDR. Как-то так она пишется... |
| Автор: Alexeis 17.8.2015, 15:50 | ||
ОС закрывает соединение при возникновении любой неисправимой ошибки. Но это не имеет отношения к теме обсуждения. Автор спрашивал как проверить закрыт или открыт сокет, а не соединение. Сокет может быть открытым как при открытом так и при закрытом соединениях. Есть еще вариант проверки при помощи функции recv . После ожидания таймаута открытый сокет с открытым соединением вернет EAGAIN или EWOULDBLOCK. Закрытый сокет или в состоянии ошибки вернет код ошибки моментально. Но этот способ страдает таймаутом, так что не эффективен. |