Функция отключения сокетов Berkley, насколько важна?

в качестве фона у меня есть встроенное устройство, которое общается со сторонним сервером по IP. Код на стороннем сервере вряд ли изменится. В недавнем выпуске я изменил функцию отключения ip для вызова shutdown () перед вызовом close () (ранее она вызывала только close ()). Встроенное устройство отключается, не завершив сеанс связи, при возникновении определенных прерываний. Когда это происходит не в том месте сеанса, сервер создает файл трассировки, который по разным причинам неприемлем для клиента. Это происходит только тогда, когда вызывается завершение работы, сервер рассматривает это как ошибку, с которой не удалось отправить (и создает файл трассировки), в то время как он обрабатывает более резкое close () как ошибку отключения другого конца, которая не требует трассировки.

Итак, очевидное решение - перестать вызывать выключение. Ответ г-на Барнса на этот вопрос дает хорошее описание этих двух функций, но если вы знаете, что к конкретному сокету подключен только один процесс, есть ли причина использовать выключение перед закрытием?

Спасибо, Патрик


person Patrick    schedule 18.06.2009    source источник
comment
Какой стек TCP вы используете во встроенном устройстве и на стороннем сервере? Не все TCP-стеки ведут себя одинаково относительно. shutdown против close. Кроме того, вы устанавливаете параметр SO_LINGER?   -  person cjs    schedule 18.06.2009
comment
Как определить стек TCP? Мы действительно используем SO_LINGER на нашей стороне.   -  person Patrick    schedule 18.06.2009
comment
Начните с того, что сообщите нам, какие операционные системы (или библиотеки) и версии задействованы.   -  person cjs    schedule 18.06.2009


Ответы (2)


Мне кажется, что «внезапное отключение» стало частью вашего протокола связи, что не очень хорошо. Если клиент работает долго после «возникновения определенных прерываний», чтобы решить, использовать ли shutdown() или close() и иметь это влияние на то, что видит другой конец, было бы лучше обновить ваш протокол, чтобы надежно доставить «этот сеанс прерван. сообщение."

Тем не менее, это звучит так, как будто эта система (то есть все взаимодействующее программное обеспечение) заморозила один бит (на сервере) настолько сильно, что такого рода изменения никогда не произойдут. Вероятно, что вы хотите сделать, вместо того, чтобы выяснять, в чем проблема на самом деле, - это заставить менеджера подписаться на быстром и грязном решении "просто используйте close()", объяснив ему, что вы не совсем уверены, в чем это могло иметь другие эффекты, но раньше все, казалось, шло нормально. (Вы не заметили исчезновения каких-либо других ошибок с тех пор, как вы внесли это изменение, не так ли?)

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

person cjs    schedule 18.06.2009
comment
Клиент не запускается после возникновения прерывания, единственная проблема заключается в том, что он неверно интерпретирует постепенное завершение работы как ошибку, которую необходимо отслеживать, в то время как вполне счастлив принять прямое закрытие. В любом случае он продолжает работать без проблем, только этот побочный эффект файла трассировки ... В любом случае хороший совет, иногда вам просто нужно заставить все работать так, как этого хочет клиент, спасибо. - person Patrick; 18.06.2009

Если вы знаете, что к конкретному сокету подключен только один процесс, есть ли причина использовать выключение перед закрытием?

Нет, нет. Вопреки большому количеству документации. Close выполняет рукопожатие закрытия FIN / ACK, если оно еще не было отправлено.

РЕДАКТИРОВАТЬ: однако это не означает, что выключение не имеет смысла: конечно, есть. Если вы хотите прекратить отправку и хотите, чтобы получатель знал об этом, но хотите продолжать получать, это то, для чего это нужно. Другое использование - почти решить проблему двух армий и синхронизировать закрытие: если вы читаете EOS, отправьте выключение и закрытие; если вы хотите инициировать закрытие, отправьте завершение работы и прочтите до EOS, а затем закройте. Если ваш протокол приложения правильный, последний шаг не должен считывать какие-либо данные, и закрытие на обоих концах будет происходить практически одновременно.

person user207421    schedule 07.12.2010