2011-05-16 105 views
2

我的Java程序出現問題。它在服務器和許多客戶端之間有一個套接字連接。這裏是服務器(這涉及問題的部分):Java,使用套接字連接發送消息的問題

private static ArrayList<ParallelServer> clientConnected = new ArrayList<ParallelServer>(); 


public Server(int port) { 
    this.port = port; 
    if (!startServer()) 
     JOptionPane.showMessageDialog(new JFrame(""), 
       "Error!", "ERROR!", 
       JOptionPane.ERROR_MESSAGE); 
} 

private boolean startServer() { 
    try { 
     server = new ServerSocket(port); 
     loadDatabase(); 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
     return false; 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } 
    return true; 
} 

public void runServer() { 
    while (true) { 
     try { 
      client = server.accept(); 
      ParallelServer pServer = new ParallelServer(client); 
      clientConnected.add(pServer); 
      Thread thread = new Thread(pServer); 
      thread.start(); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 


public static void sendBroadcast(String username) throws IOException { 
    for(int i = 0; i < clientConnected.size(); i++) 
     clientConnected.get(i).sendAnswer("@change," + username); 
} 

並行服務器是:

private Socket client; 
    private InputStreamReader inputstreamreader; 
    private BufferedReader bufferedreader; 
    private PrintWriter printwriter; 

    public ParallelServer(Socket client) { 
     this.client = client; 
    } 

    public void run() { 
     try { 
      inputstreamreader = new InputStreamReader(client.getInputStream()); 
      bufferedreader = new BufferedReader(inputstreamreader); 
      printwriter = new PrintWriter(client.getOutputStream(), true); 
      String lineread = ""; 

      while (client.isConnected()) { 
       lineread = bufferedreader.readLine(); 
       doCommand(lineread); 
      } 
     } catch (UnknownHostException unhe) { 
     } catch (InterruptedIOException intioe) { 
     } catch (IOException ioe) { 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void sendAnswer(String answer) throws IOException { 
     printwriter = new PrintWriter(client.getOutputStream(), true); 
     printwriter.println(answer); 
     printwriter.flush(); 
    } 

,這裏是客戶端:

private String serverurl = "localhost"; 
private int serverport = 7777; 
private PrintWriter printwriter; 
private InputStreamReader inputstreamreader; 
private BufferedReader bufferedreader; 
private Socket server; 

public Client() { 
    server = null; 
    try { 
     server = new Socket(serverurl, serverport); 
     server.setSoTimeout(5000); 
    } catch (UnknownHostException unhe) { 
     System.out.println("UnknownHostException: " + unhe.getMessage()); 
    } catch (InterruptedIOException intioe) { 
     System.out.println("Timeout while attempting to establish socket connection."); 
    } catch (IOException ioe) { 
     JOptionPane.showMessageDialog(new JFrame(),"Unable to reach the server!","ERROE!",JOptionPane.ERROR_MESSAGE); 
    } 
} 

public String sendCommand(String command) throws IOException { 
    if(server == null) { 
     try { 
      server = new Socket(serverurl, serverport); 
      server.setSoTimeout(5000); 
     } catch (UnknownHostException unhe) { 
      System.out.println("UnknownHostException: " + unhe.getMessage()); 
     } catch (InterruptedIOException intioe) { 
      System.out.println("Timeout while attempting to establish socket connection."); 
     } catch (IOException ioe) { 
      JOptionPane.showMessageDialog(new JFrame(),"Unable to reach the server!","ERROR!",JOptionPane.ERROR_MESSAGE); 
     } 
    } 
    if(server != null) { 
     printwriter = new PrintWriter(server.getOutputStream(), true); 
     printwriter.println(command); 
     printwriter.flush(); 
     inputstreamreader = new InputStreamReader(server.getInputStream()); 
     bufferedreader = new BufferedReader(inputstreamreader); 

     return bufferedreader.readLine(); 
    } 
    else 
     return "@serverProblem"; 
} 

該方案是一個簡單的在線遊戲輪流。玩家的輪流是用隊列創建的,當玩家輪到他時,服務器發送一條廣播消息,其中說:「現在是'玩家1'轉。」 (例如)。我的問題是,當客戶收到消息時,它就像添加了答案「現在是'玩家1'轉。」到它將收到的下一條消息。就我而言:當一名球員輪到他時,他會發送「@ passTurn,username」。 ParallelServer類從隊列中輪詢它,將它放在隊列底部,發送客戶端「@ok」告訴它輪到已成功更改,並通知服務器類發送廣播消息。然後,當同一客戶嘗試做進一步行動時,它會考慮「現在是'玩家1'轉。」作爲服務器給它的答案。相反,我希望服務器和客戶端能夠一如既往地工作,當廣播消息正常時,通知客戶端沒有任何附帶影響。 我能做什麼? 謝謝。

+0

您的輸出是在控制檯還是IDE?另外,你確定你沒有看到之前被緩存的消息嗎? – Vern 2011-05-16 01:20:02

+0

@Vern:我的輸出是一個IDE。關於緩衝區,它發生這樣的事情:客戶端發送「@passTurn」 - >服務器發送「@ok」 - >客戶端接收它 - >服務器然後發送「@ changeTurn,player1」(客戶端什麼都不做,因爲它沒有發送消息,而不是等待答案) - >客戶端發送「@otherAction」並讀取「@ changeTurn,player1」作爲答案。 – Simon 2011-05-16 01:43:32

+0

那麼,在那個消息交換的哪一點是失敗? – Vern 2011-05-16 02:02:33

回答

1

你的雙向信息傳遞機制應該是這個樣子:

服務器:

Wait on any client InputStream 
if (broadcast) 
    broadcast_message() 
else 
    process_message() 

客戶:

Receiving Thread: 
Wait on server broadcast 

Sending Thread: 
Wait on messages to be sent to server from the User Input 

這應該做的伎倆:)

希望能幫助到你。乾杯!

+0

我不能用這種方式寫服務器,因爲在InputStream之後沒有發送廣播消息。我嘗試按照您的建議組織客戶端,創建一個新的線程來等待廣播消息,但是bufferedreader已經搞亂了(我的想法是從兩個不同的bufferedreader上的相同輸入流中讀取,但它不起作用) 。也許我應該嘗試使用互斥鎖來達到這個目的。 – Simon 2011-05-16 18:56:48

+0

用不斷監聽服務器的線程完成。使用if(bufferedreader.isReady())並每隔3秒讀取一次答案,通信正常工作。無論如何,感謝給我使用兩個不同線程的想法! :) – Simon 2011-05-17 01:54:10

+0

嘿,別擔心!很高興你設法讓事情奏效,我總是樂於幫助!乾杯! – Vern 2011-05-17 06:58:25