Если вы используете блокирующую команду read (), у вас почти всегда должен быть другой управляющий поток, который отвечает за его выключение и очистку сокета.
Как правило, однако, я бы использовал вызов select (), который истекает через 1 секунду или около того, чтобы проверить, есть ли данные для чтения, и каждый цикл тайм-аута проверяет, был ли установлен флаг состояния выключения другим потоком.
Но если вы используете чистую блокировку, используйте поток управления, как вы предлагаете.