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

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

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

Регистрация: Jan 2007
Адрес: [1,1,1]
Сообщений: 135
Записей в блоге: 2
Отправить сообщение для PeTa4eK с помощью ICQ
По умолчанию Java xSocket сервер, зависание. Как исправить?

Всем привет. Где-то полторы недели назад, прочитал статью о том как создать простой сервер на Java, подключая к нему Flash.
Вот она: http://giantflyingsaucer.com/blog/?p=205

После этого в порыве восторга, начал делать игру. Делал быстро, попутна изучая способы взаимодействия - оптимизации. За основу был взят сервер из статьи, т.к. я знаю Java, на уровне стандартного языка(тоесть условия, перемнные) написал простенькую проверку на версию флешки(дабы блокировать людей с прошлой версии)

Собственно основной класс сервера:

Код:
package xsocketchatserver;

import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.channels.ClosedChannelException;
import java.util.*;
import org.xsocket.*;
import org.xsocket.connection.*;


public class xSocketDataHandler implements IDataHandler, IConnectHandler, IDisconnectHandler
{
    private Set<INonBlockingConnection> sessions = Collections.synchronizedSet(new HashSet<INonBlockingConnection>());
            
    public boolean onData(INonBlockingConnection nbc) throws IOException, BufferUnderflowException, ClosedChannelException, MaxReadSizeExceededException 
    {
        try
        {
            String data = nbc.readStringByDelimiter("\0");
            // Expected Message Format:
            // USERNAME|MESSAGE
            // ie: JohnDoe~Hello World
            
            if(data.trim().length() > 0)
            {   
               // System.out.println("Incoming data: " + data);
                
                if(data.equalsIgnoreCase("<policy-file-request/>"))
                {
                    nbc.write("<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"8090\"/></cross-domain-policy>\0");
                    return true;
                }

                String[] NewData = data.split("~");

                if(NewData[1].equalsIgnoreCase("VERSION")) {
                    String[] FirstData = NewData[0].split("§");

                    if(FirstData[1].equalsIgnoreCase("10")) {
                        sendMessageToAll(nbc, FirstData[0], "YES");
                    } else {
                        sendMessageToAll(nbc, FirstData[0], "NO");
                    }
                    //sendMessageToAll(nbc, NewData[0], NewData[1]);
                } else {
                    sendMessageToAll(nbc, NewData[0], NewData[1]);
                }
               
                //if(message[1].equalsIgnoreCase("SHUTDOWN"))
                   // Main.shutdownServer();
            }
        }
        catch(Exception ex)
        {
            System.out.println("onData: " + ex.getMessage());
        }
        
        return true;
    }
    
    private void sendMessageToAll(INonBlockingConnection nbc, String user, String message)
    {
        try
        {
            synchronized(sessions)
            {
                Iterator<INonBlockingConnection> iter = sessions.iterator();
                
                while(iter.hasNext())
                {
                    INonBlockingConnection nbConn = (INonBlockingConnection) iter.next();
                    
                    if(nbConn.isOpen())
                        nbConn.write(user +"~"+ message + "\0");
                }
            }
            
            //System.out.println("Outgoing data: " + user +"~"+ message);
        }
        catch(Exception ex)
        {
            System.out.println("sendMessageToAll: " + ex.getMessage());
        }            
    }

    public boolean onConnect(INonBlockingConnection nbc) throws IOException, BufferUnderflowException, MaxReadSizeExceededException
    {
        try
        {
            synchronized(sessions)
            {
                sessions.add(nbc);            
            }
            
            System.out.println("onConnect");
        }
        catch(Exception ex)
        {
            System.out.println("onConnect: " + ex.getMessage());
        }
        
        return true;
    }

    public boolean onDisconnect(INonBlockingConnection nbc) throws IOException
    {
        try
        {
            synchronized(sessions)
            {
                sessions.remove(nbc);            
            }
            
            System.out.println("onDisconnect");
        }
        catch(Exception ex)
        {
            System.out.println("onDisconnect: " + ex.getMessage());
        }        
        
        return true;
    }
}

Игра была онлайн - реалтайм. Насчет этого не ругайте. Игра предназначалась не для интернета, а для локальной сети. Все бы хорошо, игру я сделал, сделал неплохо.

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

Может кто помочь с этой проблемой?

При подключении идет отправка трех данных:
Код AS3:
XSocket.send(...код... + "~" + "Connect");
XSocket.send(PlayerName + "~NewPlayerConnect");
XSocket.send("SERVER" + "§" + "<b>" + PlayerName.toString() + "</b>" + " зашел в игру!" + "~CHAT");
Тоесть при подключении серверу отправляются кординаты и после символа ~ команда.
При получении этих данных, сервер отправляет их всем клиентам, там уже выясняется, что где должно создаться, переместиться.

1-я команда говорит тем кто в игре что он подключился, и он появляется у них.
2-я команда говорит что он требует их данных чтобы создать их у себя. После того как сервер отправит эту команду всем клиентам, все клиенты отправят снова запрос на сервер уже о том, что они есть в игре.
3-я команда выводит сообщение в чат, о том что игрок подключился.

1. Из-за чего может быть зависание?
2. Я считаю из-за того что в одну единицу времени приходит много запросов, и сервер не выдержав нагрузки - погибает... Если так, как можно синхронизировать данные с сервером, тоесть чтобы небыло хаотичного принял-отправил? Если никак, просто попытаться уменьшить кол-во запросов? Или вообще не в этом дело?

Заранее спасибо..

Старый 01.02.2010, 17:19
Dimitry_II вне форума Посмотреть профиль Отправить личное сообщение для Dimitry_II Найти все сообщения от Dimitry_II
  № 2  
Ответить с цитированием
Dimitry_II

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

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

Предположение основано на аналогичной работе неблокирующего сервлета. Однако смущает описание функции .write() суперинтерфейса INonBlo... - IConnection: "sends ... to the remote endpoint" - то есть не помещение данных в поток для отправки, а именно отправка данных. Правда, наличие flush успокаивает. Попробуй - вдруг поможет.

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

Регистрация: Jan 2007
Адрес: [1,1,1]
Сообщений: 135
Записей в блоге: 2
Отправить сообщение для PeTa4eK с помощью ICQ
Спасибо, но попробывал.. Не помогло(((

Вот зависание с flush... И последние данные с сервера

Вот пример последних принимаемых данных:
Код:
Incoming data: FDoKENatOR~724.7§29.5§164.9§120 - данные о положении приходят каждые 0.16 сек
Outgoing data: FDoKENatOR~724.7§29.5§164.9§120 - сервер возвращает всем эти данные
Incoming data: FDoKE~593.8§151.6§-135.4§-36.4 - снова положение
Outgoing data: FDoKE~593.8§151.6§-135.4§-36.4 - возвращение положения всем
onConnect - подключение нового игрока
Incoming data: <policy-file-request/> - отправка данных о защите
Incoming data: FDoKENatOR~695.1§34.1§176.9§130.6 - получение данных о положении
onData: channel is closed (read buffer size=0) - кто-то выходит из игры и данные прерываются
Incoming data: FDoKE~572.2§130.3§-135.4§-44.3 - еще одни положения
Incoming data: H.i.M.i.K§90§62.9§24.2§50~SPAWN - данные о спавне в новом месте

Далее полное молчание сервера
До вылета сервер работал 10 минут...

Проанализировав данные я думаю что проблема в отключении игрока. onData: channel is closed (read buffer size=0) так как после нее уже нет ответа на отправленные данные.

Можно это исправить? Или может дело в Incoming data: <policy-file-request/>

Насчет захлебывания и правда я ошибся, т.к. было до 10 человек.. И все было нормально.

Буду благодарен за помощь!

PS: Еще заметил то, что нет строчки onDisconnect которая показывает отключившегося...

Да и еще одна вещь, проанализировал простое подключение - отключение

Код:
onConnect
Incoming data: <policy-file-request/> - при первом подключении флеш ругается на защиту
onData: channel is closed (read buffer size=0) - после игрока отключает
onDisconnect - он отключается
onConnect - и сразу подключается
Incoming data: FDoKE§11~VERSION
Outgoing data: FDoKE~YES
Incoming data: FDoKE~NAMEFREE
Outgoing data: FDoKE~NAMEFREE
Incoming data: FDoKE§661.2§38§48.3§7§50§0~Connect
Outgoing data: FDoKE§661.2§38§48.3§7§50§0~Connect
Incoming data: SERVER§<b>FDoKE</b> зашел в игру!~CHAT
Outgoing data: SERVER§<b>FDoKE</b> зашел в игру!~CHAT
Incoming data: FDoKE~661.2§38§48.3§-7.9
Outgoing data: FDoKE~661.2§38§48.3§-7.9
onData: channel is closed (read buffer size=0)
onDisconnect
Вобщем меня смущают первые 4 строчки, т.к. при первом подключении, флешка ругается на защиту и отключает соединение, в коде сервера видно, что сделана команда чтобы отправить данные политики безопасности. А не может быть так, что данные отправляются, но т.к. флеш отключает игрока, данные не доходят и это вызывает зависание сервера?

Добавлено через 1 час 20 минут
Хм немного покапашись и добавив небольшую проверочку, вот:

Код:
onConnect - первое подключение
Incoming data: <policy-file-request/> - требование файла политики
Политика отправлена - проверка что политика отправлена(она отправляется вовремя при 1 игроке, это я проверял)
onData: channel is closed (read buffer size=0) - флеш защита отключает сокет соединение
onDisconnect - отключение(удаление сессие)
onConnect - мгновенное переподключение флешки уже без требования безопасности
Возможно и правда дело в том, что при нескольких игроков, сервер немного нагружается, и не успевает отправить данные вовремя, из-за чего отправляет их после того как игрока отключила защита... Можно ли как-то прикрепить проверку на то, чтобы данные не отправлялись после отключения того или инного игрока?


Последний раз редактировалось PeTa4eK; 02.02.2010 в 13:49.
Старый 05.02.2010, 13:27
PeTa4eK вне форума Посмотреть профиль Отправить личное сообщение для PeTa4eK Найти все сообщения от PeTa4eK
  № 4  
Ответить с цитированием
PeTa4eK
 
Аватар для PeTa4eK

Регистрация: Jan 2007
Адрес: [1,1,1]
Сообщений: 135
Записей в блоге: 2
Отправить сообщение для PeTa4eK с помощью ICQ
Всем спасибо! Проблему решил...

Как решил - создал 2 сервера, изначально флешка подключается к первому, получает файл политики, отключает соединение(чтобы не нагружать этот сервер) и подключается уже к основному, и файл политики уже не требуется! Вот как оказалось все просто ;D

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

Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
PeTa4eK, Вы не сталкивались ли с эксепшном "Too many files"? И если да, то как его локализовали?

Как я понял из доков, xSocket кэширует в себе открытые соединения и они остаются даже после того, как клиент давно отключился, однако что-то попытки поиграть с параметрами ни к чему хорошему так и не привели.

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

Регистрация: Jan 2007
Адрес: [1,1,1]
Сообщений: 135
Записей в блоге: 2
Отправить сообщение для PeTa4eK с помощью ICQ
Я уже ушел из xSocket, на C#, ибо как-то удобней))
Соединение можно закрыть.

Глянь тутор: http://giantflyingsaucer.com/blog/?p=224
И все поймешь.

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

Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
Тутор этот я видел. ))
Сам сейчас перезжаю на Apache Mina, просто думал, вдруг чего не учел.
Уж больно простой вариант был с xSocket.

Соединения, как я понял, он кэширует у себя внутри.

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

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

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


 


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


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