如何从这些代码添加线程,因为我想让多个用户进行聊天程序?

时间:2014-02-12 15:44:27

标签: java sockets networking network-programming client-server

SampleClient.java - 完成所有客户端工作

package sampleclient;

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

public class SampleClient extends JFrame{

private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream user;
private ObjectOutputStream output;
private ObjectInputStream input; //from the server
private String message = "";
private String serverIP;
private Socket connection;
private String name;
private JTextArea contacts;
private PrintWriter toS;

//constructor
public SampleClient(String host, String username){
    super("Client");
    serverIP = host;
    name = username;
    userText = new JTextField();
    userText.setEditable(false); //not allowed to type while no one is connected
    userText.addActionListener(
        new ActionListener(){
            public void actionPerformed(ActionEvent event){
                sendMessage(event.getActionCommand());
                userText.setText("");

            }

        }
        );
    add(userText, BorderLayout.SOUTH);
    contacts = new JTextArea();
    chatWindow = new JTextArea();
    add(new JScrollPane(contacts), BorderLayout.EAST); //scroll
    contacts.append("   ONLINE CONTACTS   \n");
    add(new JScrollPane(chatWindow), BorderLayout.CENTER); //scroll
    setSize(300, 150);
    setVisible(true);
}

//connect to server
public void startRunning(){
    try {

        connectServer();
        setupStreams();
        whileChatting();

    }catch(EOFException eofException){
        showMessage("\n Client terminated connection");
    }catch (IOException ioException){
        ioException.printStackTrace();
    }finally{
        closeAll();
    }
}

//connectServer
private void connectServer() throws IOException{
    showMessage("Attempting connection... \n");
    connection = new Socket(InetAddress.getByName(serverIP), 6789); //passes to an IP Adrdress and Port Number
    showMessage("Connected to:" + connection.getInetAddress().getHostName()); //prompt
    toS = new PrintWriter(connection.getOutputStream(), true);
    toS.println(name);

}

//set up streams for sending and receive the messages
private void setupStreams()throws IOException{
    output = new ObjectOutputStream(connection.getOutputStream());
    output.flush();
    input = new ObjectInputStream(connection.getInputStream()); //receive messages
    showMessage("\n Streams are connected");

}

//actual chat
private void whileChatting()throws IOException{
    ableToType(true);
    do{
        try{
            message = (String) input.readObject();
            showMessage("\n" +message);
        }catch(ClassNotFoundException classNotFoundException){
            showMessage("\n ERROR!");
        }
    }while(!message.equals("SERVER - END"));
}

//close sockets and streams
private void closeAll(){
    showMessage("\n Closing connections..");
    ableToType(false);
    try{
        output.close();
        input.close();
        connection.close();
    }catch(IOException ioException){
        ioException.printStackTrace();
    }
}

//send messages to server
private void sendMessage(String message){
    try{
        System.out.println(name);
        output.writeObject( "\n" + name + ": " + message);
        output.flush(); //push bytes
        showMessage("\n" + name + ": " + message);

    }catch(IOException ioException){
        chatWindow.append("ERROR!");

    }
}

//Update chatWindow
private void showMessage(final String m){
    SwingUtilities.invokeLater(
            new Runnable(){
                public void run(){
                    chatWindow.append(m); //appear at the end of the conversation

                }
            }
    );

}

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

clientTest.java

    package sampleclient;
    import javax.swing.*;

    public class ClientTest {

        public String userName;
        private static JFrame frame = new JFrame("Messenger");

            private static String getUsername() {
            return JOptionPane.showInputDialog(
                frame,
                "Enter Username:",
                "Instant Messenger",
                JOptionPane.QUESTION_MESSAGE);
        }

        public static void main(String[] args){

            String username = getUsername();//getting username
            SampleClient client;                     
            client = new SampleClient("10.0.1.4", username); //localhost

            client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            client.startRunning();
        }

    }

SampleServer.java - 完成所有服务器的工作

        package sampleserver;

        import java.io.*;
        import java.net.*;
        import java.awt.*;
        import java.awt.event.*;
        import javax.swing.*;
        import java.util.*;
        import java.lang.Object.*;


        public class SampleServer extends JFrame{

            private JTextField userText; //message variable area
            private JTextArea chatWindow; //display the conversation
            private ObjectOutputStream output; //output stream->flows from my computer to the other computer
            private ObjectInputStream input; //input stream->receive stuff
            private ObjectInputStream name; //input stream->receive stuff
            private ServerSocket server; //server variable
            private Socket connection; //socket variable
            private Vector<String> users;
            private Vector<String> ips;
            private JTextArea conList;
            private PrintWriter p;
            private BufferedReader fromC;

            //constructor
            public SampleServer(){
                super("Instant Messenger");
                userText = new JTextField(); //text field
                userText.setEditable(false); //not allowed to type anything if there are no online
                userText.addActionListener(
                        new ActionListener(){
                            public void actionPerformed (ActionEvent event){
                                sendMessage(event.getActionCommand()); //sends the message
                                userText.setText("");
                            }
                        }
                );
                add(userText, BorderLayout.SOUTH);
                users = new Vector();
                ips = new Vector();
                chatWindow = new JTextArea();
                conList = new JTextArea();
                conList.setEditable(false);
                add(new JScrollPane(chatWindow));
                add(new JScrollPane(conList), BorderLayout.EAST);
                conList.append("   ONLINE USERS    \n");
                setSize(300, 150);
                setVisible(true);
            }

           //set up and run the server
           public void startRunning(){
               try {
                   server = new ServerSocket(6789, 100); //port number and only 100 can connect to the server
                   while(true){
                       try{
                           //connect and have conversation to other client
                           waitForConnection(); //waiting method
                           setupStreams(); //set up output and input stream
                           whileChatting(); //actual chat

                       }catch(EOFException eofException){
                           showMessage("\n Server ended the connection!");
                       }finally {
                           closeAll();
                       }
                   }

               }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(); //once someone asked for connection, accepts this
               //showMessage("Now connected to "+connection.getInetAddress().getHostName()); //converts the ip address to string

               ips.add(connection.getInetAddress().getHostName()); // adds ip address of client to ips vector

               fromC = new BufferedReader(new InputStreamReader(connection.getInputStream())); // gets what client sent through printwriter - username
               String s = new String(fromC.readLine()); // saves as string
               users.add(s); // saves username of client to users vector
               String con = (connection.getInetAddress().getHostName());
               showMessage(s + " / " + con + " has connected.");

               Iterator c = users.iterator(); // username iterator
               Iterator b = ips.iterator(); // ip address iterator

               while(c.hasNext()) {

                   String d = (c.next()).toString(); // gets next element in users vector
                   String e = (b.next().toString()); // gets next element in ips vector
                   conList.append(d + "\n"); // displays username in online users list
                   conList.append("(" + e + ")\n\n"); // displays ip in online users list
               }

           }

           //get stream to send and receive data
           private void setupStreams()throws IOException{
               output = new ObjectOutputStream(connection.getOutputStream()); //computer who we communicate to
               output.flush(); //bytes of information that is send to other person (leftover)
               input = new ObjectInputStream(connection.getInputStream()); //receive messages
               showMessage("\n Streams are now setup! \n");



           }

           //actual chat conversation
           private void whileChatting() throws IOException{
               String message = "You are now connected!";
               sendMessage(message); 
               ableToType(true);
               do{
                   try{
                       message = (String) input.readObject(); //views it as an object and make sure it's a string
                       showMessage("\n" + message);
                   }catch(ClassNotFoundException classNotFoundException){
                       showMessage("\nError!");
                   }
               }while(!message.equals("CLIENT - END"));

           }

           //close streams and sockets 
           private void closeAll(){
               showMessage("\n Closing connection... \n");
               ableToType(false);
               try{
                   output.close();
                   input.close();
                   connection.close();
               }catch(IOException ioException){
                   ioException.printStackTrace();

               }
           }

           //send message to other computer
           private void sendMessage(String message){
               try{
                   output.writeObject("SERVER - " +message); //sends the mesage to the output stream
                   output.flush(); //push extra bytes to user
                   showMessage("\n SERVER - " + message);
               }catch(IOException ioException){
                   chatWindow.append("\n ERROR!"); //put in the chat area

               }

           }

           //updates chatWindow
           private void showMessage(final String text){
               SwingUtilities.invokeLater( //updats GUI or threads
                       new Runnable(){
                           public void run(){
                               chatWindow.append(text); //add string at the end of the chatWindow
                           }
                       }
               );

           }

           //allow user to type
           private void ableToType(final boolean tof){
                SwingUtilities.invokeLater( //updats GUI or threads
                       new Runnable(){
                           public void run(){
                              userText.setEditable(tof); //updates the GUI
                           }
                       }
               );
           }

        }

serverTest.java

        package sampleserver;

        import javax.swing.JFrame;

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

问题是我们必须做一个客户端 - 客户端程序,我们所做的是有2台笔记本电脑,一台用于打开客户端和服务器,另一台用于客户端。 2台笔记本电脑成功连接(客户端 - 服务器)但笔记本电脑的客户端与服务器无法连接到聊天室。但是,如果第二台笔记本电脑的客户端关闭,第一台笔记本电脑可以连接到其服务器。请帮忙吗?

1 个答案:

答案 0 :(得分:0)

问题是你只为一台计算机编写了聊天应用程序,因为它没有为每个客户端创建一个新的Thread,并进入while循环直到客户端断开连接。

//connect and have conversation to other client
waitForConnection(); //waiting method
setupStreams(); //set up output and input stream
whileChatting(); //actual chat //The problem is here, this should have been in a new Thread

将SampleServer.java更改为:

package sampleserver;

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.lang.Object.*;


public class SampleServer{

    private ObjectOutputStream output; //output stream->flows from my computer to the other computer
    private ObjectInputStream input; //input stream->receive stuff
    private ObjectInputStream name; //input stream->receive stuff
    private Socket connection; //socket variable
    private String user;
    private String ip;
    private PrintWriter p;
    private BufferedReader fromC;
    private serverTest server; //Saves the server test to append messages.

    //constructor
    public SampleServer(Socket c, String username, String userip, serverTest t){  //EDITED!!
        connection = c;
        server = t;
        ip= userip;
        user= username;             
        setupStreams(); //set up output and input stream
    }

    public void run() //This method gets called when Thread starts running
    {
        whileChatting();
        closeAll();
    }

   //get stream to send and receive data
   private void setupStreams(){
       try{
       output = new ObjectOutputStream(connection.getOutputStream()); //computer who we communicate to
       output.flush(); //bytes of information that is send to other person (leftover)
       input = new ObjectInputStream(connection.getInputStream()); //receive messages
       showMessage("\n Streams are now setup! \n");
       }catch(IOException ioException){
           ioException.printStackTrace();

       }
   }

   //actual chat conversation
   private void whileChatting(){
       String message = "You are now connected!";
       sendMessage(message); 
       do{
           try{
               message = (String) input.readObject(); //views it as an object and make sure it's a string
               showMessage("\n" + message);
           }catch(Exception e){
               //showMessage("\nError!");
           }
       }while(!message.equals("CLIENT - END"));

   }

   //close streams and sockets 
   public void closeAll(){
       showMessage("\n Closing connection... \n");
       try{
           output.close();
           input.close();
           connection.close();
       }catch(IOException ioException){
           ioException.printStackTrace();

       }
   }

   //send message to other computer
   public void sendMessage(String message){
       try{
           output.writeObject("SERVER - " +message); //sends the mesage to the output stream
           output.flush(); //push extra bytes to user
       }catch(IOException ioException){
           showMessage("\n ERROR!"); //put in the chat area

       }

   }

   //updates chatWindow
   private void showMessage(String text){
       server.showMessage(text);
   }
}

将serverTest.java更改为:

    package sampleserver;

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.lang.Object.*;

public class serverTest extends JFrame {
    private JTextField userText; //message variable area
    private JTextArea chatWindow; //display the conversation
    private ServerSocket server; //server variable
    private Vector<String> users;
    private Vector<String> ips;
    private JTextArea conList;
    private ArrayList<SampleServer> connections = new ArrayList<SampleServer>();

    public static void main(String[] args){
        new serverTest();
    }

    public serverTest()
    {
        super("Instant Messenger");
        userText = new JTextField(); //text field
        userText.addActionListener(
                new ActionListener(){
                    public void actionPerformed (ActionEvent event){
                        sendMessage(event.getActionCommand()); //sends the message
                        userText.setText("");
                    }
                }
        );
        add(userText, BorderLayout.SOUTH);
        users = new Vector();
        ips = new Vector();
        chatWindow = new JTextArea();
        conList = new JTextArea();
        conList.setEditable(false);
        add(new JScrollPane(chatWindow));
        add(new JScrollPane(conList), BorderLayout.EAST);
        conList.append("   ONLINE USERS    \n");
        setSize(300, 150);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

       try {
           server = new ServerSocket(6789, 100); //port number and only 100 can connect to the server
           while(true){
               try{
                    showMessage("Waiting for someone to connect...\n");
                    Socket connection = server.accept(); //once someone asked for connection, accepts this
                    //showMessage("Now connected to "+connection.getInetAddress().getHostName()); //converts the ip address to string

                    ips.add(connection.getInetAddress().getHostName()); // adds ip address of client to ips vector

                    BufferedReader fromC = new BufferedReader(new InputStreamReader(connection.getInputStream())); // gets what client sent through printwriter - username
                    String s = new String(fromC.readLine()); // saves as string
                    users.add(s); // saves username of client to users vector
                    String con = (connection.getInetAddress().getHostName());
                    showMessage(s + " / " + con + " has connected.");

                    Iterator c = users.iterator(); // username iterator
                    Iterator b = ips.iterator(); // ip address iterator

                    conList.setText("");

                    while(c.hasNext()) {

                        String d = (c.next()).toString(); // gets next element in users vector
                        String e = (b.next().toString()); // gets next element in ips vector
                        conList.append(d + "\n"); // displays username in online users list
                        conList.append("(" + e + ")\n\n"); // displays ip in online users list
                    }
                    final SampleServer se = new SampleServer(connection, s, con, this);
                    Thread t = new Thread(new Runnable(){
                        public void run()
                        {
                            se.run();
                        }
                    });
                    connections.add(se);
               }catch(EOFException eofException){
                   showMessage("\n Server ended the connection!");
               }
           }

       }catch(IOException ioException){
           ioException.printStackTrace();
       }
    }

    public void closeAll()
    {
        while (!connections.isEmpty())
        {
            connections.get(0).closeAll();
            connections.remove(0);
        }
    }

    public void sendMessage(String text)
    {
                showMessage("\n SERVER - " + text);
        for (SampleServer s : connections)
        {
            s.sendMessage(text);
        }
    }

    public void showMessage(final String text)
    {
       SwingUtilities.invokeLater( //updats GUI or threads
               new Runnable(){
                   public void run(){
                       chatWindow.append(text); //add string at the end of the chatWindow
                   }
               }
       );
    }
}

这里我将GUI代码移动到主类,并将serversocket移动到主类,并使SampleServer只有一个用户。当它收到消息时,它会将其添加到GUI。 只有服务器才能发送消息,服务器不会向客户端发送用户列表。