2014-11-24 5 views
0

Итак, я создаю довольно простое приложение для Java, которое в конечном итоге превратится в онлайн-игру с двумя игроками в техасский холдем. Прямо сейчас, я пытаюсь отправить несколько простых сообщений по сети, чтобы убедиться, что основные функции работают. Однако я застрял.Пока цикл не продолжается - гнездо

У меня есть два метода в классе. Один для серверов (или действительно гибрид между клиентом и сервером) и один для клиентов. Они соединяются вместе хорошо. Когда я это сделал, я заметил, что когда я подключился, они оба спамали сообщения по умолчанию (сейчас это «КЛИЕНТ: Started» и «SERVER: Started» взад и вперед друг к другу. Я понял, что это потому, что строка, содержащая эту информацию, была никогда не были опустошены, и поэтому они никогда не знали, когда прекратить передавать его. Затем я убедился, что после отправки сообщения эта переменная была обнулена, и была сделана проверка, чтобы проверить, было ли оно пустым до отправки. Вот где это пошло не так, хотя После этого они не отправят больше одного сообщения. Они отправляют свои соответствующие приветственные сообщения, но все, что я пытаюсь передать после этого, игнорируется. Это почти похоже на остановку while-loop для сервера/клиента.

Итак, у меня есть две общедоступные переменные, объявленные в классе. Они содержат любое сообщение, которое отправляет сервер или клиент.

public static String serverCommand = null;

public static String clientCommand = null;

Они являются недействительными по умолчанию, но изменен во время выполнения в GUI-части. Петля сервер выглядит следующим образом:

   while(true) 
       { 
        if((receive = receiveStream.readLine()) != null) 
        { 
         System.out.println(receive); 
        } 
        if(serverCommand != null) 
        { 
         printer.println(serverCommand); 
         printer.flush(); 
         Network.serverCommand = null; 
        } 
       } 

И клиент в то время как цикл, как это:

   while(true) 
       { 
        if(Network.clientCommand != null) 
        { 
         printer.println(clientCommand); 
         printer.flush(); 
         Network.clientCommand = null; 
        } 

        if((receive = receiveStream.readLine()) != null) 
        { 
         System.out.println(receive); 
        } 
       } 

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

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

LINK:http://hastebin.com/oqotirufic.java

ли кто-нибудь здесь есть какие-либо идеи, что происходит, и как я должен думать, пытаясь исправить/обойти это? Я добавлю, что мой опыт работы с Java и сетевым программированием очень ограничен.

EDIT

Я добавлю часть GUI, которая acccesses/изменения переменных.

+0

Где находится 'Network.clientCommand' для чего угодно? = Null? – PeterMmm

+0

Как изменяется клиентский интерфейс? – Morad

+0

Они оба изменены через графический интерфейс. Это в другом классе. Я знаю, что они оба изменены, поскольку, если я удалю настройку в нуль в приведенном выше примере, они оба изменяются (но, очевидно, сохраняют спам). ** Редактировать ** Добавлена ​​часть GUI в главном сообщении. – CmdrSharp

ответ

2

Конечно после Network.clientCommand имеет нулевое значение, больше ничего не отсылается - это то, что вы сказали это сделать:

if((receive = receiveStream.readLine()) != null) 
{ 
    System.out.println(receive); 
} 

Согласно JavaDoc, readLine() возвращает

Строка, содержащая содержимое строка, не включая символы окончания строки, или null, если конец потока достигнут.

Не «null, если есть пауза в передаче». Если он еще не видел полную строку или конец потока (разъединение сокета), ну, значит, это еще не сделано. Он ждет, пока он не получит полную строку ввода до того, как перейдет к следующей строке вашего кода.

Но откуда вы узнаете, следует ли ожидать сообщения, чтобы войти или отправить следующий? Вы не можете. Вы не можете зависеть от того, когда или что-то прибудет с другой стороны.

Что происходит, когда обеим сторонам нечего посылать? Они оба начинают ждать получения. Что происходит, когда одна сторона получает что-то новое для отправки? Ну, как только он получит что-то, он отправит его. Но этого никогда не бывает!

Что вы можете сделать, это позвонить readLine() в отдельной теме. См. JavaDocs for Thread и учебник по Java-уроку "Concurrency". И если вы используете Swing для своего графического интерфейса, см. Также урок по Java-уроку "Concurrency in Swing".

+0

Посмотрите на это! Делает прекрасный смысл, лаконичность для объяснения, что так хорошо! Я рассмотрел создание отдельного потока для readLine() - call и добавил его как для сервера, так и для клиента. Тем не менее, он все равно не получит никаких новых сообщений после первых «SERVER: Started» и «CLIENT: Started». http://hastebin.com/enilezakoq.java - это обновленный пример. Не могли бы вы предложить дальнейшие советы? – CmdrSharp

+0

Добавляя, я немного поработал. Кажется, serverCommand и clientCommand всегда «нуль» внутри фактического цикла while. Он никогда не сможет меняться во время выполнения. Это почти как если бы он застрял - любой ключ? – CmdrSharp

+0

Если вы пишете и читаете поля в разных потоках без какой-либо синхронизации, вы не можете гарантировать, что значение, которое вы написали в одном потоке, будет видно в другом потоке. Поток чтения может просто продолжать думать, что он читает старое значение. Похоже, что вы действительно хотите сделать, это передать команды в поток, который их записывает, чтобы они записывались в порядке, поэтому используйте что-то вроде ['BlockingQueue'] (http://docs.oracle.com/javase/ 8/docs/api/java/util/concurrent/BlockingQueue.html) может быть лучше. –

1

Я не могу комментировать, потому что у меня репутация менее 50 лет (я присоединился к SO несколько раз назад), вы проверили, что .readLine() - метод блокировки? если вы вызываете этот метод, пока он не будет разрешен, код будет заблокирован в этой точке.

В любом случае, попробуйте сделать system.outs внутри и снаружи цикла, чтобы обнаружить кодировку, которая блокирует ваш цикл, чтобы получить дополнительную информацию.

+0

Не должно быть. Если значение 'serverCommand' или' clientCommand' не равно null, все работает, кроме того, что он рассылает одну и ту же команду несколько раз. Не следует ли 'readLine()' в этом случае блокировать этот сценарий? – CmdrSharp

+0

, то я рекомендую вам поместить отпечатки system.out в некоторых местах кода, один внутри каждого, если и один в первой строке цикла, тогда вы можете отслеживать, будет ли ваш код туда, где он ожидается. Извините за мой английский, потому что я не родной, и я совершаю много ошибок. –

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