Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > Серверные технологии и Flash

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 14.10.2013, 12:20
Korchy вне форума Посмотреть профиль Отправить личное сообщение для Korchy Найти все сообщения от Korchy
  № 1  
Ответить с цитированием
Korchy
 
Аватар для Korchy

Регистрация: May 2011
Сообщений: 301
Записей в блоге: 2
По умолчанию Какие есть методы контроля за физическим разрывом связи с сокетном соединении?

Столкнулся с проблемой, о которой раньше даже не думал: физический разрыв сокетного соединения. Программные отсоединения клиента (переход на др. страницу и т.п.) я предусмотрел, а вот о физическом разрыве не подумал. В результате физического разрыва получаю на сервере новый переподключившийся сокет от клиента и оборванный сокет, который однако же продолжает отсылать информацию, предназначенную клиенту, в никуда, т.к он идет в списке раньше.
Какие существуют методы контроля физического разрыва со стороны сервера?
В первую очередь в голову приходит банальный пинг, но не хотелось бы нагружать соединение пустым катанием байт туда обратно.
Таймаут может быть длительным без получения от клиента данных, поэтому тоже не подходит.
Может есть что-то еще?
__________________
interplanety

Старый 14.10.2013, 12:49
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 2  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Цитата:
В первую очередь в голову приходит банальный пинг, но не хотелось бы нагружать соединение пустым катанием байт туда обратно.
Тогда никак. В любом случае байты туда сюда будут кататься, чтобы соединение было. Вообще, heartbeat используется довольно часто. Сервер просто шлет сообщение клиенту через определенные промежутки времени (у меня это сообщение _hb), на которое клиент должен сразу же ответить. Если ответа нет в течение определенного времени (скажем секунд 5), убиваем сокет. По-моему вполне нормальный вариант. За одно и время "псевдопинга" замерить можно.

Старый 14.10.2013, 14:36
Korchy вне форума Посмотреть профиль Отправить личное сообщение для Korchy Найти все сообщения от Korchy
  № 3  
Ответить с цитированием
Korchy
 
Аватар для Korchy

Регистрация: May 2011
Сообщений: 301
Записей в блоге: 2
2 caseyryan
А какой интервал времени стоит на пинг? Ну, с какой частотой сервер пингует?

И, насколько я понимаю, ответа от клиента в принципе не требуется т.к. попытка записать в оборванный сокет по любому вызовет ошибку, обработка которой закроет сокет. Хотя не, не правильно, ответ нужен. У меня же пишет, но в ошибку не вываливается.

upd: И все равно понять не могу, поможет ли мне пинг. Допустим сервер отправил пинговый байт в оба соединения, разорванное и нормальное. Из нормального ответ вернулся, значит все в порядке. Но из разорванного-то ответ не вернется, соответственно функция select не вернет мне этот сокет в списке готовых на чтение. Можно бегать по всему списку работающих сокетов, проверяя по времени, не вернулся ли ответ, скажем через минуту. Но тогда select теряет смысл.

upd1: Пока в голову приходит только такой способ - хранить в связке с указателем на сокет id пользователя (что и так делается) и при попытке создания второго сокетного соединения с тем же id рубить первое. Проблемным останется момент, когда обрыв связи у пользователя произойдет до высылки им его id. Тогда в списке повиснет неидентифицированный сокет, но такие можно рубить допустим раз в час принудительно. В любом случае двух каналов для одного пользователя не будет и данные не будут улетать с сервера в пустоту.
__________________
interplanety


Последний раз редактировалось Korchy; 14.10.2013 в 15:32.
Старый 14.10.2013, 15:36
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 4  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Цитата:
А какой интервал времени стоит на пинг? Ну, с какой частотой сервер пингует?
Я просто скомуниздил идею с юнион платформы
Поэтому у меня как у них 900 милисекунд (и 6000 на ожидание ответа). Но это значение указывается в xml файле настроек сервера, так что всегда можно легко поменять.
Цитата:
upd: И все равно понять не могу, поможет ли мне пинг. Допустим сервер отправил пинговый байт в оба соединения, разорванное и нормальное. Из нормального ответ вернулся, значит все в порядке. Но из разорванного-то ответ не вернется, соответственно функция select не вернет мне этот сокет в списке готовых на чтение. Можно бегать по всему списку работающих сокетов, проверяя по времени, не вернулся ли ответ, скажем через минуту. Но тогда select теряет смысл.
Что-то недопонял. А зачем бегать по списку? У меня все эти операции выполняются в классе обертке. Ну, то есть внутри одного экземпляра, который держит сокет, и проиходит его общение с клиентом и проверки на валидность подключения. Для удаления этого экземпляра из общего списка, если соединение отвалилось, посылается событие ClientEvent.DISCONNETED. Систему событий написал подобную флешевой, только попроще (ну привык я так ), по этому событию экземпляр просто сносится из карты хэшей менеджером подключений, и дергается метод dispose()

Старый 14.10.2013, 16:23
Korchy вне форума Посмотреть профиль Отправить личное сообщение для Korchy Найти все сообщения от Korchy
  № 5  
Ответить с цитированием
Korchy
 
Аватар для Korchy

Регистрация: May 2011
Сообщений: 301
Записей в блоге: 2
Цитата:
Что-то недопонял. А зачем бегать по списку?
А как вы узнаете о том, что на сокет поступили данные от клиента? Для того, чтобы не бегать по всем подключениям подряд используют select или poll в зависимости от языка, получая на выходе только те сокеты, которым есть что сказать. Скорее всего и у вас все точно так же.
Я же отправив в оба сокета (разорванный и рабочий) пинг получу при следующем вызове select только рабочий. Разорванный как был неактивен, так им и остается. Наверное можно сделать, что при ответе в рабочем сокете сбросится таймер пинга, а в разорванном соотв-но он будет дальше расти и при последующих вызовах пинга в каждом сокете проверять не прошло ли время на пинг + время на ответ и обрывать если прошло. Хотелось бы получить проблемный сокет в селекте, но видимо это невозможно.
Поэтому мне пока больше нравится вариант с проверкой по id. Так проверка будет выполняться только при коннекте, а не каждые 900 мс. Правда в таком случае, если пользователь запустит два окна, они будут рвать соединение друг у друга
__________________
interplanety

Старый 14.10.2013, 16:49
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 6  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Цитата:
А как вы узнаете о том, что на сокет поступили данные от клиента? Для того, чтобы не бегать по всем подключениям подряд используют select или poll в зависимости от языка
Похоже мы друг друга не понимаем малость.

Допустим клиент коннектится к серверу, при этом создается новый объект Client, через который и происходит все общение с flash клиентом.
Он начинает через 900 милисекунд слать этому клиенту сообщение _hb (в независимости от того, шлются какие-то другие сообщения или нет). При отправке _hb сообщения, фиксируется время его отправки. С этого момента начинается ожидание ответа клиента. Если в течение 6000 милисекунд клиент ничего не ответил, соединение считается дохлым. Все ридеры и райтеры глушатся, и отправляется событие дисконнекта. Менеджер клиентов его получает, и сносит target клиент из общего списка. Таким образом в списке всегда только живые сокеты.
Цитата:
Хотелось бы получить проблемный сокет в селекте, но видимо это невозможно.
Точно так же по событию DISCONNECTED можно его в список проблемных затолкать. Только зачем?

Старый 14.10.2013, 19:08
Korchy вне форума Посмотреть профиль Отправить личное сообщение для Korchy Найти все сообщения от Korchy
  № 7  
Ответить с цитированием
Korchy
 
Аватар для Korchy

Регистрация: May 2011
Сообщений: 301
Записей в блоге: 2
Цитата:
Похоже мы друг друга не понимаем малость.
Да, наверное . Я часто сумбурно излагаю, сорри.

У вас есть список подключенных клиентов. Как у вас сервер понимает, что от клиента N пришли данные?
__________________
interplanety

Старый 15.10.2013, 01:20
ShockWave512 вне форума Посмотреть профиль Отправить личное сообщение для ShockWave512 Посетить домашнюю страницу ShockWave512 Найти все сообщения от ShockWave512
  № 8  
Ответить с цитированием
ShockWave512

Регистрация: Dec 2007
Адрес: NA
Сообщений: 741
Отправить сообщение для ShockWave512 с помощью Skype™
Я вот так и не врубился в проблему флеш сокета, если не пинговать и не слать данные, то время жизни подключения где то до 5-и минут, больше не живет
пинг прекрасно работал, но кушал канал, серверное время и вооще мешал спокойно спать ночами
в итоге просто сделал микро-пинг с клиента, отсылал раз в две минуты один символ, сервер на него не реагирует, зато линк постоянно находится в "живом" состоянии.
Со стороны сервера пинг не имел смысла, там разрыв "заснувшего" соединения почему то прекрасно отрабатывается, первая версия сервер-сокета была пхп, сейчас .net/c#

Старый 15.10.2013, 08:00
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 9  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Цитата:
У вас есть список подключенных клиентов. Как у вас сервер понимает, что от клиента N пришли данные?
(сразу опустим отправку файла политик)
1) Флеш клиент стучится на сервер
2) На сервере ClientManager принимает подключение и создает объект Client.
3) В класс клиента при этом передается объект ServerSocket, который и производит все общение с флеш клиентом.

Все. Клиент создан, и помещен в карту ClientMap<String, Client> // строчный ключ равен ID клиента, он всегда уникален. Его знает и флеш клиент и сервер.

Внутри класса Client есть метод, который занимается мониторингом всех входящих сообщений и парсингом протобафа (его использовал как протокол общения).
Клиент получает сообщение, обрабатывает его, и шлет событие
Код AS3:
ClientEvent event = new ClientEvent(ClientEvent.MESSAGE, this);
event.setMessage(message);
dispatchEvent(event);
У события есть методы preventDefault() и stopPropogation() / stopImmediatePropagation()
Работают так же как во флеше. Если при получении события где-нибудь, например в комнате, в которой находится клиент дернуть метод preventDefault(), то флеш клиентам, подключенным к комнате, это сообщение не разошлется. Если нет, то, соответственно, оно будет отправлено всем клиентам в комнате (с указание ID клиента, который отправил сообщение). У сообщения есть так же свойство scope. По умолчанию это пустая строка. Если в это свойство добавить, например id конкретной комнаты, то сообщение будет распространено только среди клиентов этой комнаты. Если нет, то оно будет разослано во все комнаты, к которым подключен клиент.
Список клиентов так же есть локальный для каждой комнаты. При добавлении клиента в комнату, ему автоматически добавляются слушатели событий DISCONNECTED, LEAVE и еще некоторых. Поэтому при прохождении какого-то из событий, локальный список клиентов автоматически корректируется


Последний раз редактировалось caseyryan; 15.10.2013 в 08:23.
Старый 15.10.2013, 09:10
bifidokk вне форума Посмотреть профиль Отправить личное сообщение для bifidokk Найти все сообщения от bifidokk
  № 10  
Ответить с цитированием
bifidokk
 
Аватар для bifidokk

Регистрация: Jan 2011
Сообщений: 200
Цитата:
Сообщение от ShockWave512 Посмотреть сообщение
Я вот так и не врубился в проблему флеш сокета, если не пинговать и не слать данные, то время жизни подключения где то до 5-и минут, больше не живет
пинг прекрасно работал, но кушал канал, серверное время и вооще мешал спокойно спать ночами
в итоге просто сделал микро-пинг с клиента, отсылал раз в две минуты один символ, сервер на него не реагирует, зато линк постоянно находится в "живом" состоянии.
Со стороны сервера пинг не имел смысла, там разрыв "заснувшего" соединения почему то прекрасно отрабатывается, первая версия сервер-сокета была пхп, сейчас .net/c#
а что на пхп ипользовали? и как у вас получилось до 5 минут?) у меня часами соединение работает) причем при разрыве по таймауту (libevent к примеру это позволяет) всё отлично отрабатывает. пинг тут совершенно не нужен. при физическом отключении, насколько я помню, были проблемки того, что сервер не реагировал и оставлял коннект, но есть список socket id -> user id по которому дисконнектились все "старые" коннекты и добавлялся новый.

Создать новую тему Ответ Часовой пояс GMT +4, время: 01:42.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 01:42.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.