2015-06-20 41 views
0

我剛剛完成了關於創建即時信使聊天的youtube series,它通過套接字在服務器和一個客戶端之間工作。但是,我想改善此聊天,以便多個客戶端可以同時連接。更新雙向java信使聊天,以允許多用戶

服務器工作正常,第一個客戶端也是如此。在第一個客戶端窗口我打開,我得到消息:

Attempting connection... 
Connected to 127.0.0.1 
Streams are now setup! 
SERVER - You are now connected! 

但第二個客戶端的窗口,我打開,流沒有得到建立,而我只得到了以下消息

Attempting connection... 
Connected to 127.0.0.1 

我聽說我需要多線程來解決這個問題,但是我不太清楚我該怎麼做。

這些都是我的文件:

ChatServerTest

import javax.swing.JFrame; 

public class ChatServerTest { 
    public static void main(String[] args) { 
     ChatServer server = new ChatServer(); 
     server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     server.startRunning(); 
    } 
} 

的ChatServer

import java.io.*; 
import java.net.*; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class ChatServer extends JFrame { 

    private JTextField userText; 
    private JTextArea chatWindow; 
    private ObjectOutputStream output; 
    private ObjectInputStream input; 
    private ServerSocket server; 
    private Socket connection; 

    int port = 1234; // Test port 

    //constructor (GUI) 
    public ChatServer() { 
     super("Instant Messenger (Server)"); 
     userText = new JTextField(); 
     userText.setEditable(false); 
     userText.addActionListener(
       new ActionListener() { 
        public void actionPerformed(ActionEvent event){ 
         sendMessage(event.getActionCommand()); 
         userText.setText(""); 
        } 
       } 
      ); 
     add(userText, BorderLayout.NORTH); 
     chatWindow = new JTextArea(); 
     add(new JScrollPane(chatWindow)); 
     setSize(300,150); 
     setVisible(true); 
    } 

    //set up and run the server 
    public void startRunning(){ 
     try{ 
      server = new ServerSocket(port); 
      while(true){ 
       try{ 
        waitForConnection(); 
        setupStreams(); 
        whileChatting(); 
       }catch(EOFException eofException){ 
        showMessage("\nServer ended the connection!"); 
       }finally{ 
        closeCrap(); 
       } 
      } 
     }catch(IOException ioException){ 
      ioException.printStackTrace(); 
     } 
    } 

    //wait for connection, then display connection information 
    private void waitForConnection() throws IOException{ 
     showMessage("Waiting for someone to connect... \n"); 
     connection = server.accept(); 
     showMessage("Now connected to " + connection.getInetAddress().getHostName()); 
    } 

    //get stream to send and receive data 
    private void setupStreams() throws IOException{ 
     output = new ObjectOutputStream(connection.getOutputStream()); 
     output.flush(); 
     input = new ObjectInputStream(connection.getInputStream()); 
     showMessage("\nStreams are now setup!\n"); 
    } 

    //during the chat conversation 
    private void whileChatting() throws IOException{ 
     String message = "You are now connected!"; 
     sendMessage(message); 
     ableToType(true); 
     do{ 
      try{ 
       message = (String) input.readObject(); 
       showMessage("\n" + message); 
      }catch(ClassNotFoundException classNotFoundException){ 
       showMessage("\nERROR: Not a string"); 
      } 
     }while(!message.equals("CLIENT - END")); 
    } 

    private void closeCrap(){ 
     showMessage("\nClosing connections...\n"); 
     ableToType(false); 
     try{ 
      output.close(); 
      input.close(); 
      connection.close(); 
     }catch(IOException ioException){ 
      ioException.printStackTrace(); 
     } 
    } 

    //send a message to client 
    private void sendMessage(String message) { 
     try{ 
      output.writeObject("SERVER - " + message); 
      output.flush(); 
      showMessage("\nSERVER - " + message); 
     }catch(IOException ioExcenption){ 
      chatWindow.append("\nERROR: Can't send message"); 
     } 
    } 

    //updates chatWindow 
    private void showMessage(final String text){ 
     SwingUtilities.invokeLater(
      new Runnable(){ 
       public void run(){ 
        chatWindow.append(text); 

       } 
      } 
     ); 
    } 

    //let the user type stuff into their box 
    private void ableToType(final boolean tof) { 
     SwingUtilities.invokeLater(
      new Runnable(){ 
       public void run(){ 
        userText.setEditable(tof); 
       } 
      } 
     ); 
    } 

} 

ChatClientTest

import javax.swing.JFrame; 

public class ChatClientTest { 
    public static void main(String[] args) { 
     String IP = "127.0.0.1"; 
     ChatClient client; 
     client = new ChatClient(IP); 
     client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     client.startRunning(); 
    } 
} 

ChatClient

import java.io.*; 
import java.net.*; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class ChatClient extends JFrame { 

    private JTextField userText; 
    private JTextArea chatWindow; 
    private ObjectOutputStream output; 
    private ObjectInputStream input; 
    private String message = ""; 
    private String serverIP; 
    private Socket connection; 

    int port = 1234; // Test port 

    //constructor 
    public ChatClient(String host){ 
     super("Instant Messenger (Client)"); 
     serverIP = host; 
     userText = new JTextField(); 
     userText.setEditable(false); 
     userText.addActionListener(
      new ActionListener(){ 
       public void actionPerformed(ActionEvent event){ 
        sendMessage(event.getActionCommand()); 
        userText.setText(""); 
       } 
      } 
     ); 
     add(userText, BorderLayout.NORTH); 
     chatWindow = new JTextArea(); 
     add(new JScrollPane(chatWindow), BorderLayout.CENTER); 
     setSize(300, 150); 
     setVisible(true); 

    } 

    //connect to server 
    public void startRunning(){ 
     try{ 
      connectToServer(); 
      setupStreams(); 
      whileChatting(); 
     }catch(EOFException eofException){ 
      showMessage("\nClient terminated connection."); 
     }catch(IOException ioException){ 
      ioException.printStackTrace(); 
     }finally{ 
      closeCrap(); 
     } 
    } 

    //connect to server 
    private void connectToServer() throws IOException{ 
     showMessage("Attempting connection...\n"); 
     connection = new Socket(InetAddress.getByName(serverIP), port); 
     showMessage("Connected to " + connection.getInetAddress().getHostName()); 
    } 

    //set up streams to send and receive messages 
    private void setupStreams() throws IOException{ 
     output = new ObjectOutputStream(connection.getOutputStream()); 
     output.flush(); 
     input = new ObjectInputStream(connection.getInputStream()); 
     showMessage("\nStreams are now setup!"); 
    } 

    //while chatting with server 
    private void whileChatting() throws IOException{ 
     ableToType(true); 
     do{ 
      try{ 
       message = (String) input.readObject(); 
       showMessage("\n" + message); 
      }catch(ClassNotFoundException classNotFoundException){ 
       showMessage("\nUnknown object type"); 
      } 
     }while(!message.equals("SERVER - END")); 
    } 

    //close the streams and sockets 
    private void closeCrap(){ 
     showMessage("\nClosing down..."); 
     ableToType(false); 
     try{ 
      output.close(); 
      input.close(); 
      connection.close(); 
     }catch(IOException ioException){ 
      ioException.printStackTrace(); 
     } 
    } 

    //send messages to server 
    private void sendMessage(String message){ 
     try{ 
      output.writeObject("CLIENT - " + message); 
      output.flush(); 
      showMessage("\nCLIENT - " + message); 
     }catch(IOException ioException){ 
      chatWindow.append("\nMessage failed to send."); 
     } 
    } 

    //change/update chatWindow 
    private void showMessage(final String message){ 
     SwingUtilities.invokeLater(
      new Runnable(){ 
       public void run(){ 
        chatWindow.append(message); 

       } 
      } 
     ); 
    } 

    //gives user permission to type text into the text box 
    private void ableToType(final boolean tof){ 
     SwingUtilities.invokeLater(
      new Runnable(){ 
       public void run(){ 
        userText.setEditable(tof);  
       } 
      } 
     ); 
    } 

} 

在事先我讚賞並感謝所有樣的反應,我可以得到:)

+0

什麼問題? –

+0

這段代碼沒有問題,它的工作原理應該是這樣的,它只是爲了讓multiplie客戶端連接到服務器而改進。第一個客戶端可以沒有問題地連接到服務器,在那裏消息「嘗試連接... 連接到127.0.0.1 流現在設置! 服務器 - 你現在連接!出現,但在第二個客戶端窗口的流不連接,我只收到消息「嘗試連接... 連接到127.0.0.1」 – PloxCake

+0

StackOverflow是編程問題。您需要自己嘗試並實施,然後在出現問題時再回到這裏,告訴我們問題到底是什麼。正如你現在的帖子,這不是一個問題 –

回答

0

Althoug有點過於廣泛,所以,我會給你一個怎樣的策略來處理這種服務器端客戶端程序。欲瞭解更多信息,只需打你最喜歡的搜索機。必須有大量的文章。

服務器處理多個客戶端請求的基本策略是這樣的:

while (true) { 
    accept a connection; 
    create a thread to deal with the client; 
    start that thread; 
} 

這樣,新創建(開始)線程同時運行。這可以讓運行此服務器代碼的線程回到while (true)循環,並停止在「接受連接」行,有效地等待下一個客戶端。

所以,基本上你應該有類似

while (true) { 
    connection = server.accept(); 
    Thread clientHandler = new Thread(new ClientHandler(connection)); 
    clientHandler.start(); 
} 

這需要實現Runnable它做所有的客戶端通信類ClientHandler

請注意,應該重構程序的許多部分。你的班級ChatServer正在做太多的工作。它甚至延伸到JFrame。我的建議在同一聯賽中發揮,只是一條開始的道路。通常,您不應爲每個傳入的客戶端請求創建新的線程,而是使用有限的線程池。