2010-07-02 3 views
2

Фон:Как подождать, пока ваше сообщение TCP не будет ACKed

У нас есть клиент/серверное приложение, которое использует постоянное соединение с сервером.

Тесты показывают, что во много раз быстрее использовать уже открытое соединение, чем тратить значительное время (2,5 секунды) на создание нового соединения (крипто).

К сожалению, прежнее соединение может быть устаревшим.

Есть ли способ дождаться результата на системном уровне отправки сообщения [ACK или ошибка]?

Ожидание чтения, а затем получение конца потока вызывает путаницу.

Я знаю, что сообщение может быть разбито на пакеты. Для моих целей это было бы одинаково хорошо знать, будь то какая-либо часть сообщения была отброшена или все это было. Интересной проблемой здесь является устаревшее соединение.

ответ

1

К сожалению, прежнее подключение может быть быть устаревшим.

В этом случае вы получите исключение, когда будете писать ему, в конце концов.

Есть ли способ, чтобы ждать результата на уровне системы отправки сообщения [либо ACK или ошибка]?

No.

Ожидание чтения и затем получать конец потока приводит к путанице.

Смущение кому? Это код job для обработки путаницы. Если вы получаете неожиданный EOS, сверстник закрыл соединение или промежуточный брандмауэр, и в этом случае вам придется иметь дело с ним.

Я знаю, что сообщение может быть разбито в пакеты.

Совершенно не имеет значения. У вас нет никакого контроля над этим или любой его видимостью. Вы получаете поток байтов, завершенный EOS или исключение.

Подойдёт мои цели одинаково хорошо знать, либо , если какая-либо часть сообщения была acked или, если все это было.

Нет, это не так. ACK только означает, что он дошел до уровня TCP/IP для сверстников. Что ваше приложение заинтересовано в том, попало ли оно в одноранговое приложение, и только одноранговое приложение может сказать вам, что через ACK на уровне приложения-протокола. ACK TCP/IP здесь не помогают.

Интересная проблема здесь - это устаревшее соединение.

И это довольно тривиальная проблема. Вы можете обнаружить его в коде, и вы можете справиться с ним. Производители баз данных делали это на протяжении десятилетий. Не ракетостроение, и ничего, что требует знания TCP ACK.

+0

«ACK означает, что он имеет только TCP/IP-стек peer». Это достаточно для меня. Я пытаюсь отличить чрезвычайно распространенный отказ от крайне редкого. – Joshua

+0

@Joshua Это не «достаточно хорошо» для вас, так как вы не можете его обнаружить. – EJP

0

На уровне, на котором вы обрабатываете TCP-связь, вам не нужно беспокоиться о ACK. Это работа слоя 3 и ниже. Для вашего протокола всегда выполняются запросы команды/ответа. Ответ должен быть там независимо от успеха или ошибки. Интерпретация отсутствия ответа в качестве успеха опасна, так как нарушение связи может привести к такому же эффекту.

Я не знаю, что вы подразумеваете под черным. Поскольку TCP - это протокол, ориентированный на соединение, соединение есть или нет. Поэтому я не совсем понимаю, какие у вас проблемы: если вы потеряете связь, вам нужно приложить усилия для создания нового.

+0

Stale означает, что соединение было давно отключено брандмауэром с состоянием, но ни один из них не знает об этом. – Joshua

+0

(или иногда что-то еще, что не соблюдает keepalives) – Joshua

0

Сам стек TCP вряд ли сообщит вам своевременно, если соединение более не является жизнеспособным (если оно не локально не работает, и ОС может сообщать о локальных сбоях стека). Из-за тайм-аута повторной передачи (см. here) и что бы это ни было, может потребоваться «достаточно времени» до того, как запись вернет сообщение об отсутствии соединения. Это, конечно, по дизайну, просто дизайн не согласуется с тем, что вы хотите сделать.

Вы можете попробовать использовать TCP keep alives, но IMHO это не стоит усилий, и вы бы лучше реализовали ACK какого-то уровня приложения, если это возможно, чтобы вы могли заставить ваш протокол уровня приложения отправлять обратно ответ, как только он получит некоторые данные от вас. Если вы не можете этого сделать, и ваш запрос вызывает ответ с другого конца соединения, вы можете просто настроить таймер в зависимости от того, сколько времени вы готовы ждать ответа, прежде чем считать, что соединение мертво. По истечении таймера вы закрываете соединение и устанавливаете новый.

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

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

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