Dimitry_II
16.01.2010, 22:49
Вопрос назрел внезапно и его не получается разрешить уже несколько дней ... пока только лишь локализовать проблему.
Сразу скажу, что на локальном сервере при разработке и тесте все работает замечательно (не из-под среды флеша, а как локальный веб-проект).
Сервер на Java, поэтому для теста на удаленном сервере в качестве веб-сервера поставил Apache Tomcat (6.0.20), у которого в качествен входных портов заменил его 8080 на обычный 80 - чтобы избежать вопросов и проблем с настройкой Apache Web Server или IIS. Коннектор на HTTP1.1 поставил с неблокирующим IO - Http11NioProtocol - для работы с Comet.
Сокет создаю вполне стандартный:
public class Connection extends Socket {
public function Connection() {
super();
Security.loadPolicyFile("xmlsocket://mysite.com:843");
addEventListener(Event.CLOSE, closeHandler);
addEventListener(Event.CONNECT, connectHandler);
addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
super.connect("mysite.com", 80);
}
override public function close():void {...
private function ioErrorHandler(event:IOErrorEvent):void {...
private function securityErrorHandler(event:SecurityErrorEvent):void {...
private function closeHandler(event:Event):void {...
public function sendPacket(send_packet:ConnectionObject):void {
var packet:String = '{"action_id":' + send_packet.action_id + ',"action_type":' + send_packet.action_type + ',"message":"' + send_packet.message + '"}';
try {
writeUTFBytes('\r\n');
writeUTFBytes(new Number(packet.length).toString(16) + '\r\n' + packet + '\r\n');
flush();
} catch(exception:IOError) {
trace(exception);
}
}
private function connectHandler(event:Event):void {
writeUTFBytes("GET /comet HTTP/1.1\r\nHost: mysite.com" + "\r\nTransfer-Encoding: chunked\r\nCookie: JSESSIONID=" + {тут полученный со страницыJSESSIONID} + "\r\n");
sendPacket({пользов.объект с ID команды для запуска});
}
private function socketDataHandler(event:ProgressEvent):void {
var loaded_str:String = readUTFBytes(event.bytesLoaded);
var packets:Array = Chunked.decode(loaded_str);
for (var i:int = 0; i < packets.length; i++) {
var message:Object = JSON.decode(packets[i]);
var recieve_object:ConnectionObject = new ConnectionObject(message.action);
if (recieve_object != null) dispatchEvent(new CustomEvent(CustomEvent.RECIEVE_DATA_EVENT, recieve_object));
}
}
}
Начинка socketDataHandler не должна волновать - пока я хочу просто на входе получить строку - ответ сервера.
Соединение и отправка осуществляется по сценарию: получаем политику (все пучком - на сервере демон на 843 порту и на запрос клиента возвращает '<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>'), затем коннектимся к серверу и отправляем запрос с Transfer-Encoding: chunked, куда также добавлен ID сессии для получения доступа к атрибутам сессии.
Запрос благополучно уходит, CometServlet также благополучно его обрабатывает, подхватывает сессию, извлекает данные гостя (клиента) и помещает в коллекцию гостей со всеми параметрами, в частности, с респонсом для дальнейшего общения с клиентом. После установления соединения клиент отправляет первый пакет (в коде это sendPacket({пользов.объект с ID команды для запуска});), в ответ на который сервер производит манипуляции и отправляет флеш-клиенту ответ. Все перечисленные действия подтверждены логами Томкета (я уже расставил где только можно).
Для просмотра движений по сети поставил сниффер (Wireshark), вот его логи сразу после ответа серверного 843-го моему:
от меня серверу:
GET /comet HTTP/1.1
Host: mysite.com:80
Transfer-Encoding: chunked
Cookie: JSESSIONID=6306F2AB5A17DF1BA25F54238560313B
сервер тут же ответил:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Sat, 16 Jan 2010 17:51:00 GMT
и пакет:
4d
{"action":{"action_id":101,"action_type":1,"sender":2,"message":"Guesttttt"}}
То есть все как и должно быть. Их там еще пару штук пришло (видно из логов).
Однако флешка не среагировала никак! Что бы я ни делал, как бы не менял - событие ProgressEvent.SOCKET_DATA не срабатывает! Хотя при локальном соединении при ВСЕХ идентичных параметрах (только mysite.com заменен на 127.0.0.1:8080) все отрабатывает отлично.
Вначале я грешил на Томкет сервера, что он неправильно ставит заголовки (типа появляется Content-Length: 0), но после установки сниффера все встало на места - на мою сетевую карту сервер возвращает абсолютно валидный ответ, сервер работает точно в соответствии со сценарием и т.д.
Что копать, где копать - не знаю, потому прошу помощи.
Также если есть люди, занимающиеся подобной тематикой (в частности, онлайн-играми), вполне ли удачный протокол, транспорт и способ я выбрал? - Вроде по скорострельности весьма (судя до временным логам сниффера), также радует возможность CometServlet чутко реагировать не только на соединение и получение данных, но также определять разрыв и его причину (таймаут, обложка клиента, сервера и т.д.). Томкет в качестве сервера явление временное - сначала поставил IIS (сервер на винде 2003) - но после 2 дней мытарств оказалось, что IIS 6.0 не хочет нормально работать с chunked. Поэтому пока нормальная эволюция - Apache Web Server (возможно, RedHat).
Сразу скажу, что на локальном сервере при разработке и тесте все работает замечательно (не из-под среды флеша, а как локальный веб-проект).
Сервер на Java, поэтому для теста на удаленном сервере в качестве веб-сервера поставил Apache Tomcat (6.0.20), у которого в качествен входных портов заменил его 8080 на обычный 80 - чтобы избежать вопросов и проблем с настройкой Apache Web Server или IIS. Коннектор на HTTP1.1 поставил с неблокирующим IO - Http11NioProtocol - для работы с Comet.
Сокет создаю вполне стандартный:
public class Connection extends Socket {
public function Connection() {
super();
Security.loadPolicyFile("xmlsocket://mysite.com:843");
addEventListener(Event.CLOSE, closeHandler);
addEventListener(Event.CONNECT, connectHandler);
addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
super.connect("mysite.com", 80);
}
override public function close():void {...
private function ioErrorHandler(event:IOErrorEvent):void {...
private function securityErrorHandler(event:SecurityErrorEvent):void {...
private function closeHandler(event:Event):void {...
public function sendPacket(send_packet:ConnectionObject):void {
var packet:String = '{"action_id":' + send_packet.action_id + ',"action_type":' + send_packet.action_type + ',"message":"' + send_packet.message + '"}';
try {
writeUTFBytes('\r\n');
writeUTFBytes(new Number(packet.length).toString(16) + '\r\n' + packet + '\r\n');
flush();
} catch(exception:IOError) {
trace(exception);
}
}
private function connectHandler(event:Event):void {
writeUTFBytes("GET /comet HTTP/1.1\r\nHost: mysite.com" + "\r\nTransfer-Encoding: chunked\r\nCookie: JSESSIONID=" + {тут полученный со страницыJSESSIONID} + "\r\n");
sendPacket({пользов.объект с ID команды для запуска});
}
private function socketDataHandler(event:ProgressEvent):void {
var loaded_str:String = readUTFBytes(event.bytesLoaded);
var packets:Array = Chunked.decode(loaded_str);
for (var i:int = 0; i < packets.length; i++) {
var message:Object = JSON.decode(packets[i]);
var recieve_object:ConnectionObject = new ConnectionObject(message.action);
if (recieve_object != null) dispatchEvent(new CustomEvent(CustomEvent.RECIEVE_DATA_EVENT, recieve_object));
}
}
}
Начинка socketDataHandler не должна волновать - пока я хочу просто на входе получить строку - ответ сервера.
Соединение и отправка осуществляется по сценарию: получаем политику (все пучком - на сервере демон на 843 порту и на запрос клиента возвращает '<?xml version="1.0"?><cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>'), затем коннектимся к серверу и отправляем запрос с Transfer-Encoding: chunked, куда также добавлен ID сессии для получения доступа к атрибутам сессии.
Запрос благополучно уходит, CometServlet также благополучно его обрабатывает, подхватывает сессию, извлекает данные гостя (клиента) и помещает в коллекцию гостей со всеми параметрами, в частности, с респонсом для дальнейшего общения с клиентом. После установления соединения клиент отправляет первый пакет (в коде это sendPacket({пользов.объект с ID команды для запуска});), в ответ на который сервер производит манипуляции и отправляет флеш-клиенту ответ. Все перечисленные действия подтверждены логами Томкета (я уже расставил где только можно).
Для просмотра движений по сети поставил сниффер (Wireshark), вот его логи сразу после ответа серверного 843-го моему:
от меня серверу:
GET /comet HTTP/1.1
Host: mysite.com:80
Transfer-Encoding: chunked
Cookie: JSESSIONID=6306F2AB5A17DF1BA25F54238560313B
сервер тут же ответил:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Sat, 16 Jan 2010 17:51:00 GMT
и пакет:
4d
{"action":{"action_id":101,"action_type":1,"sender":2,"message":"Guesttttt"}}
То есть все как и должно быть. Их там еще пару штук пришло (видно из логов).
Однако флешка не среагировала никак! Что бы я ни делал, как бы не менял - событие ProgressEvent.SOCKET_DATA не срабатывает! Хотя при локальном соединении при ВСЕХ идентичных параметрах (только mysite.com заменен на 127.0.0.1:8080) все отрабатывает отлично.
Вначале я грешил на Томкет сервера, что он неправильно ставит заголовки (типа появляется Content-Length: 0), но после установки сниффера все встало на места - на мою сетевую карту сервер возвращает абсолютно валидный ответ, сервер работает точно в соответствии со сценарием и т.д.
Что копать, где копать - не знаю, потому прошу помощи.
Также если есть люди, занимающиеся подобной тематикой (в частности, онлайн-играми), вполне ли удачный протокол, транспорт и способ я выбрал? - Вроде по скорострельности весьма (судя до временным логам сниффера), также радует возможность CometServlet чутко реагировать не только на соединение и получение данных, но также определять разрыв и его причину (таймаут, обложка клиента, сервера и т.д.). Томкет в качестве сервера явление временное - сначала поставил IIS (сервер на винде 2003) - но после 2 дней мытарств оказалось, что IIS 6.0 не хочет нормально работать с chunked. Поэтому пока нормальная эволюция - Apache Web Server (возможно, RedHat).