2013-03-01 2 views
0

Я озадачен поведением приложения, использующего TCP. Когда приложение на одном конце TCP-соединения в Интернете вызывает close() в сокете, функция close() возвращается. На другом конце, однако, write() в сокете не указывает, что соединение TCP закрыто. AFAIK, это поведение несовместимо со спецификацией TCP: активный close() не должен возвращаться до тех пор, пока он не получит подтверждение с другого конца TCP-соединения (в частности, состояние TCP на активном конце не может перейти от TIME_WAIT_1, если он не получает соответствующий ответ от другого конца - в этот момент write() на другом конце должен возвращать ошибку).Что может привести к тому, что активный TCP будет возвращаться без уведомления пассивного конца?

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

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

Моей средой является Unix, C, ONC RPC и сокеты.

+0

Вы уверены, что соединение не было закрыто, и приложение просто не знает об этом, пока оно не будет '' read() '/' write() 'на нем? Так как ядро ​​ОС в конечном счете управляет соединениями, 'close()' на самом деле может работать корректно, ожидая ответа от пульта перед возвратом. Но тогда удаленное ядро ​​знает, что соединение закрыто, но не может уведомить приложение, пока оно каким-то образом не попытается получить доступ к этому соединению позже ... Вам нужно будет отслеживать пакеты, чтобы знать наверняка, я думаю ... – twalberg

+0

@twalberg Пассивный-закрытый конец TCP-соединения либо находится в системном вызове write(), либо вскоре вызовет write(). –

ответ

0

Вы объединяете переходы состояния протокола и поведение API. В RFC ничего не говорится о том, что API close() не может вернуться в приложение, а действия протокола выполняются асинхронно, и это именно то, что происходит в Sockets API по умолчанию. Если ожидающие данные будут отправляться в буфер отправки сокета, а приемник медленный, для отправки FIN может потребоваться произвольное количество времени. Вы можете изменить это, установив тайм-аут задержки с опцией SO_LINGER сокета, который закрывает блок до тех пор, пока все данные не будут сброшены или истечет время ожидания, но практически никогда не используется на практике.

+0

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

Смежные вопросы