Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Ошибки при пересоединении сокета. (http://www.flasher.ru/forum/showthread.php?t=198030)

MOHCTEP 18.04.2013 03:58

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

//В конструкторе создан сокет и слушатели
sender = new Socket();
initListeners()
...
private function initListeners():void {
                        sender.addEventListener(Event.CONNECT, onSenderConnect);
                        sender.addEventListener(ProgressEvent.SOCKET_DATA, onSendData);
                        sender.addEventListener(Event.CLOSE, onSenderClosing);
                        sender.addEventListener(IOErrorEvent.IO_ERROR, onIOErr);
                        sender.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurErr);/**/
}
//Получаем профиль и соединяемся...
public function set profile(value:Object):void {
                        for (var i:String in value) this[i] = value[i];
                        sender.connected?sender.close():null;
                        sender.connect(host, int(port));
                }

При получении следующего профиля, сокет пересоединяется, обрабатываются данные и, по завершении, запрашивается очередной профиль. Иногда сокет не может соединиться (качество связи) и выбрасывает, соответственно Error #2031: Socket Error. Это безобразие диспатчится контроллеру и он командует загрузку следующего профиля. И теперь все следующие, после "ошибочного", соединения выдают эту же ошибку, хотя они исправны на деле. Пробовал полностью обновлять сокет, на каждом профиле, проблема осталась. Если же соединения исправны, то и единственный сокет нормально разруливает все данные.
Возможно ли как-то победить это?

iflamberg 18.04.2013 14:44

Там, по-моему, надо каждый раз создать новый экземпляр сокета.

MOHCTEP 18.04.2013 15:59

Цитата:

Пробовал полностью обновлять сокет, на каждом профиле, проблема осталась.
Наверное недорассказал. Обновление и подразумевало - создание нового сокета, с предварительным уничтожением предыдущего. Вот вариант с обновлением.
Код AS3:

//
                private function newSenderSocket():Socket {
                        var s:Socket = new Socket();
                        s.addEventListener(Event.CONNECT, onSenderConnect);
                        s.addEventListener(ProgressEvent.SOCKET_DATA, onSendData);
                        //sender.addEventListener(Event.CLOSE, onSenderClosing);
                        s.addEventListener(IOErrorEvent.IO_ERROR, onIOErr);
                        s.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurErr);
                        return s;
                }
 
                private function removeSenderSocket():void {
                        if (sender) {
                                sender.connected ? sender.close() : null;
                                sender.removeEventListener(Event.CONNECT, onSenderConnect);
                                sender.removeEventListener(ProgressEvent.SOCKET_DATA, onSendData);
                                sender.removeEventListener(IOErrorEvent.IO_ERROR, onIOErr);
                                sender.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurErr);
                        }
                        sender = null;
                }

Не помогло.

iflamberg 18.04.2013 16:12

Код AS3:

                private function newSenderSocket():Socket {
                        var s:Socket = new Socket();
                        s.addEventListener(Event.CONNECT, onSenderConnect);
                        s.addEventListener(ProgressEvent.SOCKET_DATA, onSendData);
                        //sender.addEventListener(Event.CLOSE, onSenderClosing);
                        s.addEventListener(IOErrorEvent.IO_ERROR, onIOErr);
                        s.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurErr);
                        return s;
                }
 
                private function removeSenderSocket():void {
                        if (sender) {
                                sender.connected ? sender.close() : null;
                                sender.removeEventListener(Event.CONNECT, onSenderConnect);
                                sender.removeEventListener(ProgressEvent.SOCKET_DATA, onSendData);
                                sender.removeEventListener(IOErrorEvent.IO_ERROR, onIOErr);
                                sender.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurErr);
                        }
                        sender = null;
                }

Ну ты здесь создаешь новый сокет-клиент в локальной переменной s, а свойство класса sender не меняется. Должно помочь, должно.

C4Grey 18.04.2013 16:21

Не совсем уверен, но поробуй остановить дальнейшую обработку события об ошибке после обработки его контроллером
Код AS3:

private function onIOErr(e:IOErrorEvent):void
{
e.PreventDefault();
ConnectNextSocket();
}


MOHCTEP 18.04.2013 16:32

2 iflamberg Все меняется. Процедура, как видите, возвращает свежий сокет. Он и становится сендером, для нового профиля. Для этого в "set profile" добавлено:
Код AS3:

//removeSenderSocket();
//sender = newSenderSocket();

Говорю ж - не спасло.
2 C4Grey )) Попробую, спасибо! Алогично конечно, но что-то не придумывается ничего.
Не спасло.
Складывается впечатление, что этот IOError, каким-то непостижимым образом кешируется и "считает", что все остальные профили гиблые.

C4Grey 18.04.2013 21:19

Возможно, стоит посмотреть нет ли какой-то ошибки при подключении:
Код AS3:

try
{
  socket.connect();
}
catch(e0:IOError)
{
}
catch(e1:SecurityError)
{
}

Да, и может стоит подключать следующий после обработки CLOSE предыдущего сокета?

MOHCTEP 18.04.2013 22:13

Что интересно, событие CLOSE не приходит. Видимо железки просто его не шлют. Однако сокет я рассоединяю же "вручную".
Код AS3:

sender.connected ? sender.close() : null;

И трейс кажет, что он не соединен в момент нового коннекта.
try-catch ничего не показал в трейсе.
Ей-ей - фантастика какая-то. Непонятно, что даже свежесозданный сокет ведет себя этак странно.

chamele0n 18.04.2013 22:37

какаето жуткая проверка
Код AS3:

if(sender && sender.connected) sender.close();

и попробуй чистить буфер после каждой отправкой
Код AS3:

sender.write.......
sender.flush();

а вообще сокеты отлично работают во флеше, обычно причиной является кривой код

MOHCTEP 18.04.2013 23:01

При наличии сокета, чистим листенеры и при этом если сокет в коннекте - принимаем меры. В чем жуть этой конкретной конструкции?
Буфер естественно чистится, однако, он-то здесь при чем?
Цитата:

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

C4Grey 19.04.2013 05:55

О событии CLOSE - имел в виду вот так:
Код AS3:

if(sender && sender.connected)
{
    sender.addEventListener(Event.CLOSE, OnSenderClose);
    sender.close();
}
...
private function OnSenderClose(e:Event):void
{
    disposeCurrentSocket();
    newSenderSocket();
}

А то получается что все слушатели событий удаляются до отключения активного сокета - может туда какая ошибка приходит...

Цитата:

try-catch ничего не показал в трейсе.
trace - не лучший способ отладки, стоит воспользоваться дебагером

P.S.
Еще буфер нужно очищать, как советует chamele0n

caseyryan 19.04.2013 07:41

Цитата:

trace - не лучший способ отладки, стоит воспользоваться дебагером
Чем в данном случае дебагер лучше трейса?

iflamberg 19.04.2013 13:41

Код AS3:

try
{
  socket.connect();
}
catch(e0:IOError)
{
}
catch(e1:SecurityError)
{
}

Мне интересно, что вы там собираетесь ловить catch'ем. Там событие ошибки возникает, а не ошибка выкидывается.

MOHCTEP 19.04.2013 15:02

2 C4Grey Как вы считаете, OnSenderClose в вашем коде когда нибудь сработает?
Писал ведь уже, что сокет отключается вручную, перед полным его диспозом. И чистка, если flush() подразумевается, тоже делается. Разве что проверю еще буфер, перед удалением сокета.
2 iflamberg Вы абсолютно правы.
Повторюсь, проблема возникает, когда какой либо из коннектов (профилей) сгенерит событие ошибки Error #2031: Socket Error, после этого все следующие коннекты генерят эту же ошибку. А вот когда луна в нужной четверти и связь исправна, то даже сокет обновлять нет необходимости. Единственный справляется отменно.

C4Grey 19.04.2013 15:09

Цитата:

Сообщение от caseyryan (Сообщение 1130434)
Чем в данном случае дебагер лучше трейса?

Тем, что можно посмотреть состояние экземпляра класса Socket...для примера, вот так:
http://flashgameblogs.ru/uploads/ima.../27/a53d57.jpg
Впрочем, сам с удовольствием использую Flash Console наравне с дебагером - любое средство пригодится в определенных условиях.

Цитата:

Сообщение от iflamberg (Сообщение 1130460)
Мне интересно, что вы там собираетесь ловить catch'ем. Там событие ошибки возникает, а не ошибка выкидывается.

Ну а вдруг :)

Добавлено через 29 минут
Цитата:

Сообщение от MOHCTEP (Сообщение 1130477)
2 C4Grey Как вы считаете, OnSenderClose в вашем коде когда нибудь сработает?
Писал ведь уже, что сокет отключается вручную, перед полным его диспозом. И чистка, если flush() подразумевается, тоже делается. Разве что проверю еще буфер, перед удалением сокета.

извини, забыл что это событие вызвается только при отключении от сервера. В одной игршке делал переподключение к серверу - там сокеты были нужны только во время самого геймплея, клиенты часто отключались-подключались, и таких пробелм не видел, потому и советовал максимально обвешаться проверками, защитный рефлекс при столкновении с неведомым :).
P.S.
Возможно, это еще один глупый совет, но попробуй подключится по таймеру через секунд 5 - на одном форуме встречал топик с похожей проблемой.

MOHCTEP 19.04.2013 22:04

C4Grey Спасибо! Я сейчас уже вполне в состоянии воспринимать любые советы.
Никак не поддается крепость вражья!))

Добавлено через 25 часов 6 минут
:) Спасибо всем! Проблема ликвидирована.

C4Grey 22.04.2013 15:59

Напиши, пожалуйста, в чем она заключалась, если не сложно.

MOHCTEP 22.04.2013 20:29

Почему-то сокет слал событие Error #2031 дважды, с промежутком в несколько миллисекунд. По первому событию переключался профиль, ловил дубль, снова переключался и софтинка сходила с ума. ))
Эти события тащат с собою св-во text, с описанием ошибки и текущим хостом. Вот по этому самому хосту я и отфильтровал повторы в обработчике и шарманка поехала.


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

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