2009-06-18 2 views
2

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

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

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

+0

Какой стек TCP вы используете во встроенном устройстве и на стороннем сервере? Не все стеки TCP имеют одинаковое поведение w.r.t. 'shutdown' против' close'. Кроме того, вы устанавливаете опцию 'SO_LINGER'? –

+0

Как определить стек tcp?Мы используем SO_LINGER в конце. – Patrick

+0

Начните с предоставления нам информации о том, какие операционные системы (или библиотеки) и версии задействованы. –

ответ

4

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

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

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

+0

Клиент не запускается после прерываний, единственная проблема заключается в том, что он неправильно интерпретирует изящное завершение работы, поскольку ошибка, требующая отслеживания, в то же время очень рада принять прямое закрытие. В любом случае, он продолжает работать без проблем, только эта сторона влияет на файл трассировки ... Хороший совет в любом случае, иногда вам просто нужно, чтобы все работало так, как хочет клиент, спасибо. – Patrick

1

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

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

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