如何让多个客户端连接到服务器 java

Posted

技术标签:

【中文标题】如何让多个客户端连接到服务器 java【英文标题】:How to have multiple clients connect to a server java 【发布时间】:2013-05-11 02:38:09 【问题描述】:

我编写了一个基本的 isnatnt messager 程序,但它只允许一个客户端连接到服务器。我将在我的代码中进行哪些更改,以便它可以接受多个客户端,而不是让他们排队等待。

Client.java

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

public class Client extends JFrame

   private JTextField userText;
   private JTextArea chatWindow;
   private ObjectOutputStream output;
   private ObjectInputStream input;
   private String message = "";
   private String serverIP;
   private Socket connection;
   private JTextField UsernameField;
   private String Username;
   Color RED = new Color(255,0,0);
   Color ORANGE = new Color(255,128,0);
   Color YELLOW = new Color(255,255,0);
   Color LIGHT_GREEN = new Color(51,255,51);
   Color GREEN = new Color(0,255,0);
   Color DARK_GREEN = new Color(0,102,0);
   Color LIGHT_BLUE = new Color(51,51,255);
   Color BLUE = new Color(0,0,255);
   Color DARK_BLUE = new Color(0,0,102);
   Color PURPLE = new Color(153,0,153);



   //constructor
   public Client(String host)
      super("Azrin IM");
      serverIP = host;

      userText = new JTextField("Enter Message Here.");
      userText.addMouseListener(new MouseAdapter() 
          public void mouseClicked(MouseEvent e) 
              if (userText.getText().equals("Enter Message Here.")) // User has not entered text yet
                  userText.setText("");
          
      );



      userText.setEditable(true);
      UsernameField = new JTextField("Enter Username Here.");
      UsernameField.addMouseListener(new MouseAdapter() 
          public void mouseClicked(MouseEvent e) 
              if (UsernameField.getText().equals("Enter Username Here.")) // User has not entered text yet
                  UsernameField.setText("");
          
      );

      add(new JLabel ("Enter Username Here."));
      UsernameField.setEditable(true);
      userText.addActionListener(
         new ActionListener()
            public void actionPerformed(ActionEvent event)
                Username = UsernameField.getText();
                sendMessage(event.getActionCommand());
                userText.setText("");
                UsernameField.setText("");
            
         
      );
      add(userText, BorderLayout.SOUTH);
      add (UsernameField, BorderLayout.NORTH);
      chatWindow = new JTextArea();
      add(new JScrollPane(chatWindow), BorderLayout.CENTER);
      setSize(400,300);
      setVisible(true);
   


   //connect to server
   public void startRunning()
      try
         connectToServer();
         setupStreams();
         whileChatting();
      catch(EOFException eofException)
         showMessage("\n Client terminated connection");
      catch(IOException ioException)
         ioException.printStackTrace();
      finally
         Disconnect();
      
   

   //connect to server
   private void connectToServer() throws IOException
      showMessage("Attempting connection... \n");
      connection = new Socket(InetAddress.getByName(serverIP), 6969);
      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("\n Now connected to Server! \n");
   

   //while chatting with server
   private void whileChatting() throws IOException
      ableToType(true);
      do
         try
            message = (String) input.readObject();
            showMessage("\n" + message);
         catch(ClassNotFoundException classNotfoundException)
            showMessage("\n I dont know that object type");
         
      while(!message.equals(Username + ": END"));



   



   //close the streams and sockets
   private void Disconnect()
      showMessage("\n Disconnected.");
      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(Username + ": " + message);
         output.flush();
         showMessage("\n" + Username + ": " + message);
         if (message.equals("RED"))
          chatWindow.setForeground(RED);
         
         if (message.equals("ORANGE"))
              chatWindow.setForeground(ORANGE);
            
         if (message.equals("YELLOW"))
               chatWindow.setForeground(YELLOW);
           
         // I am aware I need to space these if staments better :) .
if (message.equals("LIGHT_GREEN"))
     chatWindow.setForeground(LIGHT_GREEN);
 
if (message.equals("GREEN"))
     chatWindow.setForeground(GREEN);

if (message.equals("DARK_GREEN"))
     chatWindow.setForeground(DARK_GREEN);

if (message.equals("LIGHT_BLUE"))
     chatWindow.setForeground(LIGHT_BLUE);

if (message.equals("BLUE"))
     chatWindow.setForeground(BLUE);

if (message.equals("DARK_BLUE"))
     chatWindow.setForeground(DARK_BLUE);

if (message.equals("PURPLE"))
     chatWindow.setForeground(PURPLE);




      catch(IOException ioException)
         chatWindow.append("\n something messed up sending message hoss!");
      
   

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

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

ClientTest.java

import javax.swing.JFrame;

public class ClientTest 
   public static void main(String[] args) 
      Client charlie;
      charlie = new Client("69.125.13.88");
      charlie.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      charlie.startRunning();
   

服务器.java

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

public class Server extends JFrame

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

   //constructor
   public Server()
      super("Azrin IM 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(500,200);
      setVisible(true);
   

   //set up and run the server
   public void startRunning()
      try
         server = new ServerSocket(6969, 100);
         while(true)
            try
               waitForConnection();
               setupStreams();
               whileChatting();
            catch(EOFException eofException)
               showMessage("\n Server 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("\n Streams 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("\n idk wtf that user sent!");
         
      while(!message.equals("CLIENT - END"));
   

   //close streams and sockets after you are done chatting
   private void closeCrap()
      showMessage("\n Closing 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("Josh A - " + message);
         output.flush();
         showMessage("\nSERVER - " + message);
      catch(IOException ioException)
         chatWindow.append("\n ERROR: DUDE I CANT SEND THAT 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);
            
         
      );
   


ServerTest.java

import javax.swing.JFrame;

public class ServerTest 
   public static void main(String[] args) 
      Server sally = new Server();
      sally.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      sally.startRunning();
   

【问题讨论】:

这个问题在过去两天里被问了 3 次...从All about Sockets 和Concurrency 开始。您需要很好地理解这些主题才能继续进行,所以我建议您从一些简单的示例开始,然后逐步进行...... IK 什么是套接字。 IT 说了一些关于必须将 serverTest.java 以线程形式放在其他地方的内容。我该怎么做? 【参考方案1】:

普通线程示例

这是“普通”线程示例,可能是您可能会发现的更常见示例之一。这样做的问题是您可能会失去对线程的控制,并且有数百个斜坡线程都在运行,消耗系统资源...

它很简单,并且确实展示了您需要实现的基本概念......

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class TestSocketThread 

    // Need away to stop the program...
    private static boolean acceptMore = true;

    public static void main(String[] args) 
        new TestSocketThread();
    

    public TestSocketThread() 
        ServerSocket serverSocket = null;
        try 
             serverSocket = new ServerSocket(6969, 100);
            while (acceptMore) 
                Socket socket = serverSocket.accept();
                new Thread(new SocketThread(socket)).start();    
            
         catch (IOException exp) 
            exp.printStackTrace();
         finally 
            try 
                serverSocket.close();
             catch (Exception e) 
            
        
    

    public class SocketThread implements Runnable 

        private Socket socket;

        public SocketThread(Socket socket) 
            this.socket = socket;
        

        @Override
        public void run() 
            // Process socket...
        
    

执行器服务示例

执行器服务更灵活,并提供对普通线程更好的管理控制,包括(根据此示例)固定线程池。

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorSocketTest 

    // Need away to stop the program...
    private static boolean acceptMore = true;

    public static void main(String[] args) 
        new ExecutorSocketTest();
    

    public ExecutorSocketTest() 
        ServerSocket serverSocket = null;
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        try 
             serverSocket = new ServerSocket(6969, 100);
            while (acceptMore) 
                Socket socket = serverSocket.accept();
                executorService.submit(new SocketCallable(socket));
            
         catch (IOException exp) 
            exp.printStackTrace();
         finally 
            try 
                serverSocket.close();
             catch (Exception e) 
            
            executorService.shutdownNow();
        
    

    /**
     *
     * @author swhitehead
     */
    public class SocketCallable implements Callable 

        private Socket socket;

        public SocketCallable(Socket socket) 
            this.socket = socket;
        

        @Override
        public Object call() throws Exception 
            // Process socket requests...
            return null;
        
    

你的工作是现在离开并阅读有关Concurrency in Java的所有信息

【讨论】:

以上是关于如何让多个客户端连接到服务器 java的主要内容,如果未能解决你的问题,请参考以下文章

如何通过JMeter将多个MQTT客户端连接到单个iothub

多个客户端如何同时连接到服务器上的一个端口,比如80?(译)

如何防止流星重新连接到服务器

多线程在 C++ 中的 Windows 中将多个客户端连接到单个服务器

多个并行tcp连接

如何在 AsyncTask 中启动客户端并连接到服务器?