Форум: "Сети";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];
ВнизПодтверждение о доставке сообщения. Найти похожие ветки
← →
NAlexey © (2004-03-23 08:34) [0]Помогите решить проблему. У меня следующая ситуация: на сервере запущен сервис с TServerSocket, к нему подключаются клиенты с TClientSocket. Все работает в асинхронном режиме. Мне необходимо реализовать механизм подтверждения доставки сообщений. Т.е если один клиент посылает сообщение другому, а тот в это время занят какой либо задачей, сообщение не доставится и я никак об этом не могу узнать. Пытаюсь делать приблизительно след образом:
1) Завел глобальную переменную Delivered: boolean;
на клиенте:
отсылаю:procedure ...
function CheckIfDeliver: boolean;
var
StartTime: TDateTime;
DT: Double;
begin
Result := False;
StartTime := Time;
while not Delivered do
begin
DT := Frac(Time - StartTime)*86400;
if DT > 5 then
Exit;
Application.ProcessMessages;
end;
Result := True;
end;
begin
Delivered := False;
Socket.SendText("#M", "Сообщение");
if not CheckIfDeliver then
...
end;
procedure TClientData.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Str: string;
begin
Str := Socket.ReceiveText;
if Copy(Str , 1, 2) = "#M" then //Сообщение получено.
begin
...
Socket.SendText("#D", ""); //Ответить что получено.
end;
if Copy(Str , 1, 2) = "#D" then //Подтверждение пришло.
Delivered := True;
2) На сервере обрабатываю, т.е просто рассылаю полученое всем клиентам.procedure TxService.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Str: string;
procedure Answ;
var
I: Integer;
begin
with ServerSocket.Socket do
for I := 0 to ActiveConnections - 1 do
Socket.SendText(Str);
end;
begin
Answ(Socket.ReceiveText);
end;
Данный подход почемуто не работает, подозреваю что гдето происходит рассинхронизация. Как вообще реализуются такие вещи?
← →
Piople © (2004-03-23 08:37) [1]Клиент после получения сообщения просто отправляет на сервак поддтверждение получения сообщения
← →
Verg © (2004-03-23 08:38) [2]Сходу могу только одно сказать.
> procedure Answ;
> var
> I: Integer;
> begin
> with ServerSocket.Socket do
> for I := 0 to ActiveConnections - 1 do
> Socket.Connections[I].SendText(Str);
> end;
>
← →
Verg © (2004-03-23 08:40) [3]Мфу ты, сам запутался
> Connections[I].SendText(Str);
Тут кто-то правильно говорил - забудьте про With - ошибок будет меньше
← →
NAlexey © (2004-03-23 08:48) [4]>Verg © (23.03.04 08:40) [3]
Здесь дело не в синтаксических ошибках, в оригинале все нормально. Ошибся я при составлении примера здесь, просто хотел передать принцип по которому все работает. Здесь дело в том, что при отсылке сообщения ф-ция CheckIfDeliver должна работать(по моему мнению), а она не работает. Т.е клиент отправил, другой при получении отправил подтверждение сервер разослал подтверждение всем клиентам они должны получить и обработать флаг Dilivered а моя ф-ция в это время ждет. Но этого не происходит, она ждет до конца.
← →
Digitman © (2004-03-23 08:52) [5]
> Т.е если один клиент посылает сообщение другому, а тот
> в это время занят какой либо задачей, сообщение не доставится
>
будет доставлено !
доставкой же занят не клиент, а системные транспортные механизмы .. ведь TCP/IP - транспортный протокол с гарантией доставки (говорят так же - с квитированием доставляемых пакетов) .. механизм доставки (с квитированием или без оного)прозрачен для прикладной клиентской задачи
когда клиент освободится и будет готов к приему, он выполнит recv-метод и обязательно получит те данные, что ему адресованы, уже доставлены на этот момент и просто ожидают их выборки клиентом из очереди ввода
> Все работает в асинхронном режиме
отсюда и проблемы твои
ты просто не учитываешь особенности работы гнезда в этом режиме
кр.того, ты не учитываешь особенности поточного протокола TCP/IP, наивно полагая, что данные (в твоем случае - строковые), отправленные передатчиком по SendText, на стороне приемника после выполнения ReceiveText будут иметь тот же вид
← →
NAlexey © (2004-03-23 08:57) [6]>Digitman © (23.03.04 08:52) [5]
>будет доставлено !
Странно, действительность показывает обратное. Если приложение занято достаточно долгое время, то сообщение просто не приходит, и отсылающий ничего не говорит. Да и в справке насколько я помню написано что OnRead при асинхронном режиме не всегда получает отправленные данные. И что надо чекать OnDisconnect.
>отсюда и проблемы твои
В чем заключаются эти проблемы?
← →
Verg © (2004-03-23 09:07) [7]
> И что надо чекать OnDisconnect.
"Чекать" надо не только его. А что у тебя разрыв соединения происходит, что ли?
> Да и в справке насколько я помню написано что OnRead при
> асинхронном режиме не всегда получает отправленные данные
Это в какой такой справке так написано? Покажи
← →
NAlexey © (2004-03-23 09:11) [8]>А что у тебя разрыв соединения происходит, что ли?
Разрыва не происходит. Просто если выполнить SendText занятому приложению оно не приходит и все.
>Это в какой такой справке так написано?
TCustomSocket.OnRead:
Note: Non-blocking sockets do not always receive an OnRead event for the last bit of data passed over the connection. When using a non-blocking socket, check for any unread data in the OnDisconnect event to make sure that everything is handled.
← →
Digitman © (2004-03-23 09:14) [9]
> то сообщение просто не приходит
приходит ! а если не приходит, то связано это с буферизацией транспортируемых данных на стороне передатчика (со включенным по умолчанию алгоритмом Нагла), т.е. сообщение попросту не отправлено.. SendText() не есть факт физической отправки данных, это просто постановка данных в очередь передачи
> отсылающий ничего не говорит.
а что он, по твоему, должен "сказать" ? передатчик вызвал send, в рез-те чего данные, предназначенные к передаче, были поставлены в очередь, и получил назад управление .. далее же не его (передатчика) уже забота, как и в какие сроки эти данные будут доставлены стороне приемника
> в справке насколько я помню написано что OnRead при асинхронном
> режиме не всегда получает отправленные данные
в справке не такого.. и быть не может
вот что там написано :
Occurs when a client socket should read information from the socket connection
should read information - здесь имеется ввиду, что следует вызвать один из recv-методов гнезда, чтобы прочитать некую очередную доступную (доставленную уже !) порцию поточной инф-ции
> И что надо чекать OnDisconnect
и такого нет в справке
> В чем заключаются эти проблемы?
в том, что ты наивно полагаешь, что если передатчик выполнил SendText("AAA"), то данные немедленно (уже якобы в ходе работы вызванного send-метода) будут доставлены гнезду-приемнику, и там будет возбуждено событие OnRead, в обработчике которого метод ReceiveText вернет в точности строку "AAA"
← →
Verg © (2004-03-23 09:17) [10]Ну так и что же там написано? А написано
> check for any unread data in the OnDisconnect event to
> make sure that everything is handled
Но у тебя же НЕ происходит дисконнекта, как ты говоришь.
> Просто если выполнить SendText занятому приложению оно не
> приходит и все.
Т.е. ни OnError, ни OnDisconnect, но тем не менее не приходят?
← →
NAlexey © (2004-03-23 09:24) [11]Хм... Если вы не против, и я не отниму у вас много времени, я всетаки попрошу ответить на мой вопрос. Правильный ли я избрал подход, реально ли так получать ответ о получении сообщения. Если нет, то какой подход правильный, как реализуются эти вещи. Нужно ли использовать синхронный режим, если да, то почему и чем это чревато?
← →
Verg © (2004-03-23 09:31) [12]В любом случае, синхронные, асинхронные, блокирующие, неблокирующие ли сокеты вы используете, с ними надо правильно работать в зависимости от выбранного режима. И тогда вот этого
> Просто если выполнить SendText занятому приложению оно
> не приходит и все.
.... никогда не случится.
← →
Digitman © (2004-03-23 09:52) [13]
> Правильный ли я избрал подход
в самой идее реализовать прикладное подтверждение доставки нет ничего криминального, но подход явно неверный ... ты не имеешь права делать какие-то предположения о предельном времени фактической доставки сообщения - это время, в общем случае, зависит от множества факторов, влиять на которые прикладной процесс, использующий IP-транспорт, практически не может (за исключением, наверно, манипуляций с алгоритмом Нагла)
> реально ли так получать ответ о получении сообщения
конечно реально ! только вот какое-то определенное время ожидания квитирующего сообщения устанавливать не следует
но здесь есть другой важный момент - сообщение физически было доставлено, но квитанция может и не прийти вообще из-за нештатного разрыва транспортного канала ... в этом случае принимающая сторона не получит ни OnRead, ни OnError ни OnDisconnect, хотя гнездо будет по прежнему выглядеть активным ..
для обнаружения такой ситуации можно задействовать/реализовать т.н. KeepAlive-механизм .. либо встроенный в установленный WSP (на уровне соотв.опции, см. SetSockOpt()) либо прикладной (если WSP не реализует встроенную возможность)
прикладной KeepAlive сводится к следующему : партнеру через равные промежутки времени посылается некое предопределенное тобой сообщение-"щуп" (на которые партнер может и не отвечать).. если в рез-те ходе такого сообщения (читай - вызов одного из send-методов гнезда) возникла исключительная ситуация ESocketConnectionError либо возникло событие OnError с соотв.кодом отказа, это говорит о нештатном разрыве транспортного канала (т.е. партнер не закрывал свою сторону соединения по своей же инициативе, а, например, компьютер партнера был отсоединен от сети физически).. далее ждать каких-то данных от партнера и продолжать с ним инф.обмен бессмысленно, следует тут же закрыть свою сторону соединения
> Нужно ли использовать синхронный режим, если да, то почему
необязательно... это зависит от логики, требуемой тебе
но в ряде случаев синхр.режим использовать даже не крайне желательно, например, в случае реализации транспорта, поддерживающего механизм асинхронных обратных вызовов
неблок. режим обычно хорош при однопоточной организации сетевого приложения (как правило, клиентского), использующего прикл.протокол инф.обмена в режиме "запрос - ответ".. он прост в использовании и не требует множества доп.ресурсов
блок.режим ничем не хуже, но его, как правило, задействуют при работе с транспортом в доп.код.потоках
← →
NAlexey © (2004-03-23 10:10) [14]Спасибо за ответы, попробую изменить реализацию.
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.032 c