2015-06-20 57 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。我的建议在同一联赛中发挥,只是一条开始的道路。通常,您不应为每个传入的客户端请求创建新的线程,而是使用有限的线程池。