Другая альтернатива - создать себе фильтры NoCloseInputStream и NoCloseOutputStream, которые просто ничего не делают при закрытии; затем используйте их, чтобы обернуть потоки сокета вашего приложения (перед любым обёртыванием приложения как буфера).
Обратите внимание, что если бы вы сделали это, вам нужно было бы сохранить ссылку на сокет (или обернутые потоки), чтобы вы могли закрыть сокет, когда вы на самом деле покончили с ним.
Чтобы ответить на комментарий, что это «слишком продвинутая концепция для OP»: проблема OP в том, что при закрытии потока верхнего уровня он также закрывает нижележащий сокет, но это бесполезно, так как он хочет создать в дальнейшем потоки верхнего уровня через сокет для отправки дальнейших сообщений. В зависимости от его архитектуры, единственный способ достичь этого может заключаться в том, чтобы обернуть потоки в оболочках NoClose - например, он может передавать потоки в XML-сериализатор или десериализатор, который после завершения закрывает поток, который закрывается вне его контроля .