|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
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; } } Игра была онлайн - реалтайм. Насчет этого не ругайте. Игра предназначалась не для интернета, а для локальной сети. Все бы хорошо, игру я сделал, сделал неплохо. Но по прохождению некоторого времени, когда подключается новый игрок(перед этим много кто уходит - приходит) Или если написать сообщение в чат. Сервер просто зависает. Никакой ошибки, ничего, просто перестает отвечать на запросы. И не отключается. Единственный способ - перезапуск. Может кто помочь с этой проблемой? При подключении идет отправка трех данных: XSocket.send(...код... + "~" + "Connect"); XSocket.send(PlayerName + "~NewPlayerConnect"); XSocket.send("SERVER" + "§" + "<b>" + PlayerName.toString() + "</b>" + " зашел в игру!" + "~CHAT"); При получении этих данных, сервер отправляет их всем клиентам, там уже выясняется, что где должно создаться, переместиться. 1-я команда говорит тем кто в игре что он подключился, и он появляется у них. 2-я команда говорит что он требует их данных чтобы создать их у себя. После того как сервер отправит эту команду всем клиентам, все клиенты отправят снова запрос на сервер уже о том, что они есть в игре. 3-я команда выводит сообщение в чат, о том что игрок подключился. 1. Из-за чего может быть зависание? 2. Я считаю из-за того что в одну единицу времени приходит много запросов, и сервер не выдержав нагрузки - погибает... Если так, как можно синхронизировать данные с сервером, тоесть чтобы небыло хаотичного принял-отправил? Если никак, просто попытаться уменьшить кол-во запросов? Или вообще не в этом дело? Заранее спасибо.. |
|
|||||
Регистрация: Jan 2010
Сообщений: 211
|
Ну, если заходит второй игрок и зависает, то точно можно сказать, что это не из-за количества запросов, так как два игрока завалить сервер запросами просто не в состоянии ... рассчитано на тысячи игроков (ну, сотни-то уж точно).
Если бы ты смог локализовать ошибку (зависание), было бы проще. Из того, что сразу бросается в глаза - ты пишешь в синхронизированный поток, но не отправляешь (nbConn.flush()) - логично предположить, что пока он не очистится (отправится или перегрузится), с ним ничего не сделаешь - будет в подвешенном состоянии. Предположение основано на аналогичной работе неблокирующего сервлета. Однако смущает описание функции .write() суперинтерфейса INonBlo... - IConnection: "sends ... to the remote endpoint" - то есть не помещение данных в поток для отправки, а именно отправка данных. Правда, наличие flush успокаивает. Попробуй - вдруг поможет. |
|
|||||
Спасибо, но попробывал.. Не помогло(((
Вот зависание с 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 - данные о спавне в новом месте Далее полное молчание сервера Проанализировав данные я думаю что проблема в отключении игрока. 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 Добавлено через 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. |
|
|||||
Всем спасибо! Проблему решил...
Как решил - создал 2 сервера, изначально флешка подключается к первому, получает файл политики, отключает соединение(чтобы не нагружать этот сервер) и подключается уже к основному, и файл политики уже не требуется! Вот как оказалось все просто ;D |
|
|||||
Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
|
PeTa4eK, Вы не сталкивались ли с эксепшном "Too many files"? И если да, то как его локализовали?
Как я понял из доков, xSocket кэширует в себе открытые соединения и они остаются даже после того, как клиент давно отключился, однако что-то попытки поиграть с параметрами ни к чему хорошему так и не привели. |
|
|||||
Я уже ушел из xSocket, на C#, ибо как-то удобней))
Соединение можно закрыть. Глянь тутор: http://giantflyingsaucer.com/blog/?p=224 И все поймешь. |
|
|||||
Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
|
Тутор этот я видел. ))
Сам сейчас перезжаю на Apache Mina, просто думал, вдруг чего не учел. Уж больно простой вариант был с xSocket. Соединения, как я понял, он кэширует у себя внутри. |
Часовой пояс GMT +4, время: 07:04. |
|
« Предыдущая тема | Следующая тема » |
|
|