2014-11-24 191 views
0

好了,所以我創建一個相當簡單的Java應用程序,它最終會變成一個在線2玩家德州撲克遊戲。現在,我試圖通過網絡發送一些簡單的消息,以確保基本功能正常。然而,我卡住了。While循環不能繼續 - 插座

我有一類兩種方法。一個用於服務器端(或者實際上是客戶端和服務器之間的混合),另一個用於客戶端。他們連接在一起很好。當我提出這個問題,我注意到,當我連接,他們都垃圾郵件的默認消息(現在是「客戶:入門」和「服務器:啓動」來回海誓山盟我想這是因爲包含該信息的串是從來沒有清空,所以他們從來不知道什麼時候該停止發送它。然後,我確信,發送消息之後,該變量被清零,並檢查是爲了看它是否在發送之前爲空。 在此處,它雖然出了問題!這樣做後,他們將不再發送多條消息都沒有。他們發送其各自的歡迎訊息,但任何事情我嘗試被忽略後進行傳輸。這就像如果while循環用於服務器/客戶端停止。

所以,我在班上兩個公共變量聲明。這些文件包含的任何消息的服務器或客戶端要發送。

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和網絡編程方面的經驗非常有限。

編輯

我將添加這acccesses GUI的一部分/改變的變量。 http://hastebin.com/upadayuwug.java

+0

'Network.clientCommand'設置爲任何值!= null? – PeterMmm 2014-11-24 15:48:14

+0

clientCommand如何改變? – Morad 2014-11-24 15:51:02

+0

它們都通過GUI進行更改。它在一個不同的階級。 我知道他們都改變了,因爲如果我在上面的例子中刪除設置爲null,他們都改變(但明顯保持垃圾郵件) **編輯** 在主文章中添加了GUI部分。 – CmdrSharp 2014-11-24 15:54:24

回答

2

當然Network.clientCommand後爲空,僅此而已發送 - 這就是你告訴它做的事:

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

按照JavaDocreadLine()回報

一個包含內容的字符串該行不包含任何行終止字符;如果已到達流的末尾,則爲null

如果傳輸暫停,則不是「null」。如果它還沒有看到完整的行,或流的結束(套接字斷開),那麼它還沒有完成。它會一直等待,直到它到達您的代碼的下一行之前的全部輸入。

但是,您如何知道您是否應該等待消息進入或發出下一個消息? 你不能。你不能依靠什麼時候或者什麼東西從另一端到達。

當雙方都沒有發送時會發生什麼?他們都開始等待接收。當一方獲得新的東西發送時會發生什麼?那麼,一旦它收到了什麼,它會發送它。但那從來沒有發生過!

你可以做什麼,在一個單獨的線程中調用readLine()。請參閱JavaDocs for Thread和Java教程課程"Concurrency"。如果您使用Swing作爲GUI,請參閱Java教程"Concurrency in Swing"

+0

看那個!完美無缺,爲解釋這一點而讚歎! 我看着爲readLine()調用創建一個單獨的線程,併爲服務器和客戶端添加了這個線程。但是,它仍然不會通過第一個「SERVER:Started」和「CLIENT:Started」收到任何新消息。 http://hastebin.com/enilezakoq.java是更新的示例。你能提供進一步的建議嗎? – CmdrSharp 2014-11-24 16:34:03

+0

加上,我做了更多的挖掘。似乎serverCommand和clientCommand在實際的while循環內始終爲'null'。它在運行時永遠不會改變。這幾乎就像它被卡住了 - 任何線索? – CmdrSharp 2014-11-24 17:20:01

+0

如果您正在寫入和讀取不同線程中的字段,而沒有進行任何同步,則無法保證您在一個線程中寫入的值何時會在另一個線程中可見。閱讀線程可能會繼續認爲它正在讀取舊值。看起來你真正想要做的是將命令傳遞給寫入它們的線程,以便它們按順序寫入,所以使用類似['BlockingQueue'](http://docs.oracle.com/javase/) 8/docs/api/java/util/concurrent/BlockingQueue.html)可能會更好。 – 2014-11-24 18:23:34

1

我不能評論原因我低於50的聲望(前幾年加入),你檢查了.readLine()是一種阻塞方法?如果你調用這個方法,直到它沒有解決,代碼將被阻止在那一點上。

無論如何,儘量讓循環內外的system.out檢測阻塞循環的代碼行以獲取更多信息。

+0

不應該。如果'serverCommand'或'clientCommand'的值不爲空,除了垃圾郵件多次發送相同的命令外,一切都可以正常工作。在這種情況下不應該'readLine()'也阻止這種情況? – CmdrSharp 2014-11-24 16:00:24

+0

然後我鼓勵你將system.out打印放在代碼的一些地方,如果在循環的第一行中有一個,那麼你可以跟蹤你的代碼是否到達預期的位置。對不起,我的英語原因我不是本地人,我犯了很多錯誤。 – 2014-11-24 16:08:57