2009-02-05 6 views
1

Следуя моим предыдущим вопросам, я попытаюсь прояснить одну из проблем, с которыми я столкнулся.Программирование сокетов Java

Я пытаюсь создать многопользовательскую версию PacMan.

Простой обзор того, как я сделал свое приложение, заключается в том, что у меня есть сервер с сервером, который постоянно прослушивает определенный порт. Как только клиент подключается, он создает поток, в котором происходит вся передача данных. Сначала он прослушивает направление, в котором клиент хочет переместить, а затем отправляет обновления обратно клиенту. На стороне клиента это обратное направление отправки, а затем ожидание получения обновления. Это делается с использованием ObjectOutput/Input Streams. Существует также игровой класс, который имеет всю логику игры, и у этого есть игровой цикл, который каждый цикл вызывает каждый из подключенных игроков serverThread.exchangeDatas().

Моя игра работает нормально с подключенным одним клиентом, но как только присоединяется другой клиент (локально это все, что я тестировал, но это должно работать правильно?) Это разбило мою игру в потоке сервера, вызвав следующую ошибку: java .io.StreamCorruptedException: неверный код типа: 00.

Является ли код, который отключает это исключение

 Object o = in.readObject(); 
     if (o instanceof Direction) 
     { 
      // Get new location 
      player.setDirection((Direction) o); 
     //System.out.println("Got: " + (Direction)o + " new location: " + player.getNextLocation()); 
     } 

     // Send gameState 

     //System.out.println("Sending data"); 
     Data data = new Data(game.getGameState(), game.getScared(), game.getScareLeft(), player.getLives(), player.getScore()); 
     out.flush(); 
     out.writeObject(data); 
     out.flush(); 
     out.reset(); 

Server code

ServerThread code (the one that crashes in the exchangeData method

Client Controller code

Game loop code - line 42 is what calls the exchange data method

Любая помощь будет удивительно с этим.

http://www.mediafire.com/download.php?nwwqmzywfom

вот скачать для клиента и сервера (они NetBeans проекты)

Извините за мой грязный код = [

+0

awm ... У меня нет ничего, чтобы видеть файлы rar (и не хочу иметь: P) Стоп-функция тоже очень полезна. :) – OscarRyz

ответ

1

Многопоточность нуждается в синхронизации. Используете ли вы синхронизированный поток (или синхронизируете доступ к потоку самостоятельно)?

Обновление: Приведенный пример кода может быть вызван из нескольких потоков. Если несколько потоков обращаются к одному и тому же потоку, могут возникнуть ошибки, подобные тем, которые вы испытываете.

Предлагаю взглянуть на http://java.sun.com/docs/books/tutorial/essential/concurrency/sync.html.

Отметив метод/класс синхронизированный, среда выполнения будет следить за тем, чтобы этот метод/класс был активен не более чем в 1 поток одновременно. Это на самом деле огромная и трудная тема, поэтому уделите время изучению основ и убедитесь, что вы понимаете основную проблему. :)

+0

Я не сделал ничего подобного - есть ли у вас какие-то уроки? это, чтобы остановить потоки, прыгающие перед другими? – Malachi

+0

Да, он останавливает 2 потока от выполнения чего-то сразу. Тем не менее, вы не получаете доступ к своим потокам или сокетам из нескольких потоков, насколько я могу судить, поэтому я не думаю, что это ваша проблема. – MBCook

2

Это трудно отлаживать без остальной части кода, поэтому я собираюсь опубликовать свой первый сеанс и немного поиграть. Почему вы вызываете .reset() в своих потоках? Это переместило бы позицию чтения в поток обратно в начало, что не так, как я думал (никогда не использовал ObjectInputStream).


ОК, я взял свой код и изрубил некоторые маленькие вещи, так что бы собрать, и он работал на меня с .RESET(). Похоже, что вы делали, это правильно.

Я не думаю, что смогу больше помочь без остальной части кода. Сожалею.

PS: Я предполагаю, что у вас есть вещи Serializable, реализация Runnable и т. Д., Которые у вас не было у кода. Но если у вас не было такой настройки, тогда ваш код не будет компилироваться в первую очередь.


После беспорядка с кодом в течение 45 минут я не могу получить ошибку. Мне пришлось кое-что взломать здесь и там, чтобы он запустился (поскольку ему не хватало класс или два, а часть кода выше), но я не думаю, что я его изменил (много). Я не уверен, что мои изменения повлияют на что-нибудь, это немного сложно понять.

У меня есть два предположения относительно того, что происходит. Первое будет снова .reset(). Если вы не прокомментировали это и посмотрите, не имеет значения.

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

java.io.StreamCorruptedException: invalid type code: 00 

Я собираюсь предположить, что 00 может быть намеком. Я понимаю, что должен быть отправлен байт подписи (в качестве доказательства того, что объект - это то, что вы говорите, поэтому строки не интерпретируются как двойные или PacManGameUI), и, очевидно, Java недовольна, потому что это неправильно.

Но почему 00? Это интересная ценность. Мое предположение (и это большая догадка) заключается в том, что это первый байт целого числа (который равен 4 байтам при отправке с ObjectOutputStream.writeInt()). Возможно, у вас есть целое число, отправленное, которое не читается, прежде чем вы вызываете .readObject во входном потоке? Я не уверен, что это вызовет ошибку, но это было бы мое лучшее предположение.

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

Другой способ (и это будет более поучительно, если вы смело) слушать в разговоре между двумя половинами программы, используя что-то вроде WireShark или tcpdump. Это позволит вам видеть необработанные байты, которые вы отправляете. Хотя это может быть запутанным и трудно интерпретируемым, оно должно выяснить, легко ли вы отправляете неправильный объект. Посылка int, вероятно, составит около 4 байтов, но отправка большой структуры займет больше. Через эксперименты вы должны уметь это понять. Это боль, но она сообщит вам точно что отправляется.

Может быть сложно отследить интерфейс loopback (когда компьютер разговаривает с ним самостоятельно), по крайней мере, в Windows с помощью WireShark (я не помню, чтобы это было так просто), поэтому часто бывает проще сделать это с помощью два компьютера (один сервер, один как клиент), чтобы вы могли легко заглянуть в пакеты.

Извините, что я не могу быть более полезным.

+0

Я навсегда застрял в этой проблеме, и я не вижу, что не работает. Я загружу код для вас, чтобы посмотреть и посмотреть, можете ли вы его скомпилировать. Мой код действительно плохой, кстати ... http: //www.mediafire.com/download.php? Nwwqmzywfom – Malachi

+0

Это действительно меня беспокоит. Я принял ваш подход и просто отправил строки, а также с клиента и сервера с обработкой логики в центральном классе и произошли те же ошибки. Так что это должно быть связано с тем, как я ее реализовал. Спасибо за вашу помощь. Я думаю, что мой лектор! – Malachi

1

Возможно, что-то не в тему, но у javagaming.org есть раздел для 'OnLine Game Development & Networking'.Возможно, вы захотите это проверить.

0

Могу ли я просто спросить, что вы ожидаете, если возможно, чтобы второй клиент присоединился? Вы не сохраняете ссылку на этот объект Thread, когда происходит другая итерация, объект больше не имеет ссылки, поэтому JRE уничтожит объект, не так ли?

while (true) 
{ 
    System.out.println("Waiting for conneciton on port " + port); 
    Socket client = listener.accept(); 
    System.out.println("Accepted a connection from: " + client.getInetAddress()); 
    Thread t = new Thread(new PacManServerThread(client, game)); 
    t.start(); 
} 

Конечно, вы должны сделать что-то вроде

myGenericArray.add(t); 

в конце вашего цикла в противном случае, если объект теряет объем в цикле он будет разрушен?

+0

Нити не собирают мусор до тех пор, пока они не закончатся, насколько я знаю –

+0

Внутри класса потоков pacmanserver он вызывает метод, который создает нового игрока и передает ссылку на главную игру потока, который его назвал. this.player = game.playerJoinsGame (это); это неправильно? – Malachi

Смежные вопросы