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

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

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

Регистрация: Jan 2010
Сообщений: 211
По умолчанию js -> flash -> server (java) - теряются данные

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

1. Страница, javascript (функция, связывающая скрипт с флешем, упрощенная):
Код:
function sendData(data){
	var flash = (navigator.appName.indexOf("Microsoft") != -1) ? window["comet"] : document["comet"];
	if (typeof(flash) == undefined || flash == undefined || flash == null) return setError(/* my function */);
	flash.sendData(data);
};
2. Флеш (упрощенный код):
Код AS3:
public class Main extends Sprite {
	private var _socket:MySocket;
	function Main() {
		...
		_socket = new MySocket();
		_socket.addEventListener(CustomEvent.RECIEVE_DATA_EVENT, server_message);
		...
		ExternalInterface.addCallback("sendData", client_message);
	}
	...
	private function server_message(event:Event):void {
		try {
			var e = CustomEvent(event);
			ExternalInterface.call("recieving", e.message);
		} catch(exception:Error) {...}
	}
	private function client_message(data:String):void {
		_socket.sendPacket(data);
	}
}
Код AS3:
public dynamic class CustomEvent extends Event {
	private var _message:String;
	private var _message_type:String;
	public static const RECIEVE_DATA_EVENT:String = "RECIEVE_DATA_EVENT";
 
	public function CustomEvent(type:String, message:String, message_type:String) {
		super(type);
		_message = message;
		_message_type = message_type;
	}
	...
}
Код AS3:
public class MySocket extends Socket {
	public function MySocket() {
		addEventListener(Event.CLOSE, closeHandler);
		addEventListener(Event.CONNECT, connectHandler);
		addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
		addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
		addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
		...
	}
	private function closeHandler(event:Event):void {...}
	private function connectHandler(event:Event):void {...}
	private function ioErrorHandler(event:IOErrorEvent):void {...}
	private function securityErrorHandler(event:SecurityErrorEvent):void {...}
	private function socketDataHandler(event:ProgressEvent):void {...}
	public function sendPacket(data:String):void {
		var packet:String = '{"data":' + data + '"}';
		try {
			writeUTFBytes(new Number(packet.length).toString(16) + '\r\n' + packet + '\r\n');
			flush();
		} catch(exception:IOError) {...}
	}
}
3. Сервер (Java). Код совершенно несущественен, так как есть возможность проверить данные на входе - в них и проблема.

Код флеша я для поста сильно упростил, реально он значительно сложнее, я передаю несколько параметров, на основе которых формирую пользовательский объект, который передается и обрабатывается разными классами. Также на выходе флешки формируется достаточно сложная строка JSON (использую библиотеку для формирования). Уверен, что проблемы в упущенных деталях нет.

Уже пару месяцев использую такую цепочку для обмена данными и все работало как часики - быстро, удобно и без проблем. Проблема появилась, когда я на странице посредством js в цикле делаю много вызовов функции sendData(data) - от 3 и более. Логгирование перед отправкой во флеш показывает, что данные отправляются корректною. Скажем, посылаем строки "ааа", "bbb", "ccc".
На сервере на входе получаем первый пакет, в котором корректное значение - "ааа", а потом второй пакет, в котором значения "bbb" и "bbb". Если отправлять не 3 пакета, а, скажем, 5 пакетов, то на входе получаем те же 2 пакета, в первом все корректно, а во втором - 4 значения "bbb". Так как на сервере реализован механизм разделения целого пакета на составные, то проблема не в этом, а именно в передаваемых данных.

Подозреваю, что моя проблема связана как-то с однопоточностью выполнения AS3 и частым дерганьем ее со страницы. Однако мыслей по преодолению ее немного. Есть мысль не делать цепочку вызовов во флеше: "вызов интерфейса со страницы" - "вызов функции-обработчика" - "вызов функции-отправителя" - "отправка пакета", а на первом же этапе помещать получаемые флешкой данные в очередь, а в классе пользовательского сокета организовать изъятие данных из очереди. Правда, немного затрудняюсь в реализации (в Java это делается очень просто - через блокирующие или неблокирующие механизмы и треды, а вот в AS3 как это сделать грамотно - пока не очень представляю).

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

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

Поэтому вопрос к знающим и использующим сокеты для взаимодействия с сервером - как вы справляетесь с большим количеством отправляемых пакетов? Спасибо.

Добавлено через 2 часа 11 минут
Все-таки кое в чем был неправ ...

Анализируя двоичные данные, полученный на сервере, обнаружил интересную закономерность (пакеты слегка отредактированы, так как содержимое закодировано при отправке и распаковывается непосредственно в функциях обработки):

Отправляем 3 пакета с данными "aa", "bbbb", "cccccc". Ловим на сервере:

Пакет 1. Получен, обработан и отправлен.
- Read 154 bytes: {"action_id":210,"action_type":102,"sender":1,"message":"{'title':'aa','owner':9}","message_id":"xxx"}

Пакет 2 (пришел как спаренный их 2-го и 3-го отправленного).
- Read 156 bytes: {"action_id":210,"action_type":102,"sender":1,"message":"{'title':'bbbb','owner':9}","message_id":"xxx"}
- Read 158 bytes: {"action_id":210,"action_type":102,"sender":1,"message":"{'title':'bbbb','owner':9}","message_id":"xxx"}{"action_id":210,"action_type":102,"sender":1,"message":"{'title':'cccccc', 'owner':9}","message_id":"xxx"}

Как видно, флеш при отправке "склеивает" уже отправленный пакет и новый, или просто не очищает буфер отправки после flush(). Почему? При этом длина пакета соответствует правильному, отправляемому в настоящий момент пакету. Если отправлять большее количество данных, то количество принимаемых пакетов будет правильным, длина каждого пакета правильна, но нужный пакет будет находиться всегда в самом конце получаемых данных.

Добавлено через 6 часов 44 минуты
Ёпс! Стыдно-то как ...

Я очень давно экспериментировал с созданным механизмом обработки полученных данных (что-то у меня было проблемно с размером получаемого пакета) и добавил "+=" к стринговой переменной, в котороъ сохраняется значение пакета. Эксперимент не вернул к исходному, отсюда и ошибка

Приношу извинения, стыдно, но все проблемы мигом исчезли. Извините.

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

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

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


 


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


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