Java套接字中的群聊多线程问题

问题描述 投票:0回答:1

我发现了一些问题的实例,但不幸的是,经过几个小时,我似乎无法解决它。我基本上有一个Socket组聊天应用程序,该应用程序允许客户端登录,服务器使用数据库检查登录名,然后允许客户端移动到聊天页面或不移动到聊天页面。登录后,将按下“连接”按钮以初始化聊天的套接字连接。我到达了一个阶段,我可以有多个客户端,每个客户端可以发送一条消息,该消息将由服务器接收并发送给所有客户端,但是只有单击“发送”按钮后,其他客户端才能读取该消息。从那以后,我尝试了许多使其同步工作的方法,但是现在回到服务器将不回显消息的地步。

我希望获得有关如何更改服务器以从客户端接收消息并将它们回显给所有客户端的建议。

P.S。这是我的第一篇文章,谢谢。

服务器和处理程序代码----------------------

public class ServerHandler extends JFrame {

private static final long serialVersionUID = 1L;
private JPanel contentPane;
static JTextField tfSend;
public static JTextArea textArea;
private JScrollPane scrollPane;
static JButton btnSend;
private JButton btnSettings;




/**
 * Launch the application.
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                ServerHandler frame = new ServerHandler();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

     // server is listening on port 8000 
    ServerSocket ss = new ServerSocket(8000); 

      while (true)  
     { 
        Socket s = null; 

         try 
         { 
           //socket object to receive incoming client requests 
             s = ss.accept(); 
               textArea.setText(textArea.getText() + "\nA new client connected : " + s); 

              //obtaining input and out streams 

            ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); 
            ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
            DataOutputStream dos = new DataOutputStream(s.getOutputStream()); 
            DataInputStream dis = new DataInputStream(s.getInputStream());
            textArea.setText(textArea.getText() + "\nAssigning new thread for this client"); 


             // create a new thread object 
             ClientHandler t = new ClientHandler(s, ois, oos, dos,dis);                 
              //Invoking the start() method 
             t.start();                  

         } 
         catch (Exception e){ 
           s.close(); 
            ss.close();
             e.printStackTrace(); 
         } 
     } 
} 


public ServerHandler() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 700, 500);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setBackground(Color.LIGHT_GRAY);
    setContentPane(contentPane);
    contentPane.setLayout(null);

    btnSend = new JButton("Send");
    btnSend.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    btnSend.setBounds(542, 404, 117, 29);
    contentPane.add(btnSend);

    btnSettings = new JButton("Settings");
    btnSettings.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    btnSettings.setBounds(542, 30, 117, 29);
    contentPane.add(btnSettings);

    tfSend = new JTextField();
    tfSend.setBounds(45, 404, 490, 26);
    contentPane.add(tfSend);
    tfSend.setColumns(10);
    tfSend.setEditable(false);


    textArea = new JTextArea();
    scrollPane = new JScrollPane(textArea);
    scrollPane.setLocation(47, 71);
    scrollPane.setAutoscrolls(true);
    scrollPane.setSize(612,322);
    contentPane.add(scrollPane);
    textArea.setEditable(false);


    JLabel lblNewLabel = new JLabel("");
    lblNewLabel.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    lblNewLabel.setBounds(26, 23, 652, 429);
    contentPane.add(lblNewLabel);
}  
}
class ClientHandler extends Thread  { 
    //thread conns
    private ObjectInputStream ois; 
    private ObjectOutputStream oos; 
    private DataOutputStream dos;
    private DataInputStream dis;
    private Socket s;

    //database conns
    static Connection c;
    static Statement stmt;
    static Connection c1;
    static Statement stmt1;     
    static Connection c2;
    static Statement stmt2;


    public ClientHandler(Socket s, ObjectInputStream ois, ObjectOutputStream oos, DataOutputStream dos2,  DataInputStream dis2) {
        this.s = s;
        this.ois = ois;
        this.oos = oos;
        this.dos = dos2;
        this.dis = dis2;
    }


    @Override
    public void run()  
    {   
        try {
            System.out.println("running");
            checkUTF();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
}


    public void checkUTF() throws IOException, SQLException {
        while(true) {
            String check = null;
            check = dis.readUTF();
            System.out.println("check");
            if (check!= null) {
                System.out.println("switching");
                try {       
                    switch(check) {
                    case "chat":
                        System.out.println("chatting");
                        chat();
                    case "Login":
                        try {
                            System.out.println("checking login");
                            checkLogin();
                        } catch (SQLException e1) {
                            e1.printStackTrace();
                        }
                    }}finally { 
                        System.out.println("ending");
                        close();
                    }       
            }else {

            }
        }
    }

    public void chat() throws IOException {

        dos.writeUTF("chat");
        dos.flush();
        ServerHandler.tfSend.setEditable(true);

        while(s.isClosed()==false) {
            String check = null;
            check = dis.readUTF();

            if (check!= null) {
                if(check.equals("close")){
                    dos.writeUTF("close");
                    break;
                }else{
                    dos.writeUTF(check);
                }
            }
        }
        }



public void close() throws IOException {
    dos.close();
    dis.close();
    oos.close();
    ois.close();
    s.close();
}

public void checkLogin() throws SQLException {
    ClientStuff.LoginObject login = null;

        System.out.println("here");
        try {
            login = (LoginObject) ois.readObject();
            System.out.println(login.getName() + login.getPassword());
            String username = login.getName().trim();
            String password = login.getPassword().trim();

                if((checkLoginDetails(username,password))==true) {
                    closeDatabase();
                    String status = "Found";
                    dos.writeUTF(status);
                    dos.flush();
                    System.out.println("ending2");

                }else {
                    closeDatabase();
                    String status = "Not Found";
                    dos.writeUTF(status);
                    dos.flush();
                    System.out.println("ending3");
                    close();
                }                                                   
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
}



public static boolean checkLoginDetails(String username, String password) throws SQLException {

    startDatabaseConnections();
    stmt2 = c2.createStatement();
    ResultSet rs = stmt2.executeQuery("SELECT * FROM CLIENTINFO WHERE USERNAME = '"+username+"' AND PASSWORD = '"+password+"';");
    while ( rs.next() ) {            
        return true;
    }

    rs.close();
    return false;
}


public static void startDatabaseConnections() {

    try {
        Class.forName("org.sqlite.JDBC");
        c = DriverManager.getConnection("jdbc:sqlite:ServerInfo");
        System.out.println("Opened database successfully");
    } catch ( Exception e ) {
        System.err.println( e.getClass().getName() + ": " + e.getMessage() );
        System.exit(0);
    }

    try {
        Class.forName("org.sqlite.JDBC");
        c1 = DriverManager.getConnection("jdbc:sqlite:ClientConvo");
        System.out.println("Opened database successfully");
    } catch ( Exception e ) {
        System.err.println( e.getClass().getName() + ": " + e.getMessage() );
        System.exit(0);
    }
    try {
        Class.forName("org.sqlite.JDBC");
        c2 = DriverManager.getConnection("jdbc:sqlite:ClientInfo");
        System.out.println("Opened database successfully");
    } catch ( Exception e ) {
        System.err.println( e.getClass().getName() + ": " + e.getMessage() );
        System.exit(0);
    }
}

public static void closeDatabase() throws SQLException {
    c.close();
    c1.close();
    c2.close();
    System.out.println("Databases Closed");
}

}

客户端登录代码--------------

 public class UserLogin extends JFrame {

/**
 * 
 */
private static final long serialVersionUID = 1L;

/**
 * 
 */

static UserLogin frame;

private JPanel contentPane;
private static JTextField tfUsername;
private  static JTextField tfPassword;
static boolean yes = false;

static JButton btnNewUser = new JButton("New User");
static JButton btnLogin = new JButton("Login");

static Socket login = new Socket();
private static String serverIP = "127.0.0.1";
static ObjectOutputStream oos;
static ObjectInputStream ois;
static DataOutputStream dos;
static DataInputStream dis;

static String status = null;


/**
 * Launch the application.
 * @throws IOException 
 * @throws UnknownHostException 
 * @throws ClassNotFoundException 
 */
public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                frame = new UserLogin();
                if(frame.isVisible()==false) {
                    frame.setVisible(true);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

}
public void foundUser(String status) {
    if (status.equals("Found")) {
    frame.setVisible(false);
    dispose();
    new UserChat().setVisible(true);
}else if(status.equals("Not Found")) {
    close();
    tfUsername.setText("Not Found");
    tfPassword.setText("Not Found");
}
}

public void close(){
    System.out.println("closing");
    try {
        login.close();
        dos.close();
        dis.close();
        oos.close();
        ois.close(); 
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void connectServer() throws IOException {
    System.out.println("start stream setup");
    login = new Socket(InetAddress.getByName(serverIP), 8000);
    }

public void setupStreams() throws IOException {
    System.out.println("start stream setup 2");
    oos = new ObjectOutputStream(login.getOutputStream());      
    System.out.println("obj output stream setup");
    ois = new ObjectInputStream(login.getInputStream());
    System.out.println("obj input stream setup");
    dos = new DataOutputStream(login.getOutputStream()); 
    System.out.println("data output stream setup");
    dis = new DataInputStream(login.getInputStream());  
    System.out.println("data input stream setup");
}



/**
 * Create the frame.
 * @throws IOException 
 */
public UserLogin() throws IOException {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 700, 500);
    contentPane = new JPanel();
    contentPane.setBackground(Color.LIGHT_GRAY);
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    btnNewUser.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    btnNewUser.setBounds(373, 294, 117, 29);
    contentPane.add(btnNewUser);

    btnLogin.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    btnLogin.setBounds(373, 253, 117, 29);
    contentPane.add(btnLogin);

    tfUsername = new JTextField();
    tfUsername.setBounds(255, 175, 235, 26);
    contentPane.add(tfUsername);
    tfUsername.setColumns(10);

    tfPassword = new JTextField();
    tfPassword.setColumns(10);
    tfPassword.setBounds(255, 213, 235, 26);
    contentPane.add(tfPassword);

    JLabel lblUsername = new JLabel("Username");
    lblUsername.setBounds(127, 180, 104, 16);
    contentPane.add(lblUsername);

    JLabel lblPassword = new JLabel("Password");
    lblPassword.setBounds(127, 218, 104, 16);
    contentPane.add(lblPassword);

    JLabel lblNewLabel = new JLabel("");
    lblNewLabel.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    lblNewLabel.setBounds(26, 23, 646, 429);
    contentPane.add(lblNewLabel);

    btnNewUser.addActionListener(
            new ActionListener(){
                public void actionPerformed(ActionEvent event){
                    new UserReg().setVisible(true);
                }
            }
            );

    btnLogin.addActionListener(
            new ActionListener(){
                public void actionPerformed(ActionEvent event){
                    LoginObject userLogin = new LoginObject(tfUsername.getText(),tfPassword.getText());
                    System.out.println(userLogin.getName() + userLogin.getPassword());
                    try {
                        connectServer();
                        setupStreams();
                        dos.writeUTF("Login");
                        dos.flush();
                        System.out.println("login");
                        oos.writeObject(userLogin);
                        oos.flush();
                        System.out.println("userlogin");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    String status = null;
                    try {
                        status = dis.readUTF();
                        System.out.println(status);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    System.out.println(status);
                    foundUser(status);
                    }
                }
            );
}}

客户聊天代码---------

   public class UserChat extends JFrame {

/**
 * 
 */
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private static  JTextField tfSend;
private static JTextArea textArea;
private JScrollPane scrollPane;
private static JButton btnSend;
private JButton btnSettings;
private JButton btnLogout;
private JButton btnGetChat;
String messageIn = "";      


private static Socket login = new Socket();
private static String serverIP = "127.0.0.1";
static ObjectOutputStream oos;
static ObjectInputStream ois;
static DataOutputStream dos;
static DataInputStream dis;

static String status = null;
private JButton btnConnect;



/**
 * Launch the application.
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            UserChat frame = new UserChat();
            if(frame.isVisible()==false) {
                frame.setVisible(true);
            }
        }
    });

    System.out.println("mainnn");
    }

public static void connectServer() throws IOException {
    textArea.setText(textArea.getText()+"start stream setup\n");
    login = new Socket(InetAddress.getByName(serverIP), 8000);
    textArea.setText(textArea.getText()+"start stream setup 2\n");
    oos = new ObjectOutputStream(login.getOutputStream());      
    textArea.setText(textArea.getText()+"obj output stream setup\n");
    ois = new ObjectInputStream(login.getInputStream());
    textArea.setText(textArea.getText()+"obj input stream setup\n");
    dos = new DataOutputStream(login.getOutputStream()); 
    textArea.setText(textArea.getText()+"data output stream setup\n");
    dis = new DataInputStream(login.getInputStream());  
    textArea.setText(textArea.getText()+"data input stream setup\n");
    }


public static void whileChatting() throws IOException {
    tfSend.setEditable(true);

            if(login.isClosed()==false) {
                btnSend.addActionListener(
                        new ActionListener(){
                            public void actionPerformed(ActionEvent event){
                                String sendText = "Client - ";
                                sendText += tfSend.getText();
                                try {
                                    dos.writeUTF(sendText);
                                    dos.flush();

                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                                tfSend.setText("");
                            }
                        }
                        );

                Thread t = new MsgHandler(login, ois, oos, dis,dos, textArea); 

                t.start(); 
            }
}
/**
 * Create the frame.
 */
public UserChat() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 700, 500);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setBackground(Color.LIGHT_GRAY);
    setContentPane(contentPane);
    contentPane.setLayout(null);

    btnSend = new JButton("Send");
    btnSend.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    btnSend.setBounds(542, 404, 117, 29);
    contentPane.add(btnSend);

    btnConnect = new JButton("Connect");
    btnConnect.setBounds(165, 31, 117, 29);
    contentPane.add(btnConnect);

    btnSettings = new JButton("Settings");
    btnSettings.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    btnSettings.setBounds(542, 30, 117, 29);
    contentPane.add(btnSettings);

    btnLogout = new JButton("Logout");
    btnLogout.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    btnLogout.setBounds(37, 30, 117, 29);
    contentPane.add(btnLogout);

    btnGetChat = new JButton("Get Chat");
    btnGetChat.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    btnGetChat.setBounds(417, 30, 117, 29);
    contentPane.add(btnGetChat);

    tfSend = new JTextField();
    tfSend.setBounds(45, 404, 490, 26);
    contentPane.add(tfSend);
    tfSend.setColumns(10);
    tfSend.setEditable(false);

    textArea = new JTextArea();
    scrollPane = new JScrollPane(textArea);
    scrollPane.setLocation(47, 71);
    scrollPane.setAutoscrolls(true);
    scrollPane.setSize(612,322);
    contentPane.add(scrollPane);
    textArea.setEditable(false);

    JLabel lblNewLabel = new JLabel("");
    lblNewLabel.setBorder(new BevelBorder(BevelBorder.RAISED, null, null, null, null));
    lblNewLabel.setBounds(26, 23, 652, 429);
    contentPane.add(lblNewLabel);

    btnLogout.addActionListener(
            new ActionListener(){
                public void actionPerformed(ActionEvent event){
                    try {
                        dos.writeUTF("logout");
                        dos.flush();
                        System.out.println("Servers Closed");   
                        dispose();
                        setVisible(false);
                        UserLogin.main(null);
                    } catch (IOException | ClassNotFoundException e) {
                        e.printStackTrace();
                    }

                }
            }
            );
    btnConnect.addActionListener(
            new ActionListener(){
                public void actionPerformed(ActionEvent event){

                        try {
                            connectServer();
                            dos.writeUTF("chat");
                            dos.flush();
                            String chat = dis.readUTF();
                            System.out.println(chat);
                                if(chat.equals("chat")) {
                                    System.out.println(chat);
                                    btnConnect.setVisible(false);
                                    whileChatting();
                                }
                        } catch (IOException e) {
                            e.printStackTrace();
                            System.out.println("Here");
                        }

                    }
                }
            );

    }
  }



 class MsgHandler extends Thread{
final ObjectInputStream ois; 
final ObjectOutputStream oos; 
final Socket s; 
DataOutputStream dos;
DataInputStream dis;
JTextArea textArea;

public MsgHandler(Socket s, ObjectInputStream ois, ObjectOutputStream oos, DataInputStream dis2, DataOutputStream dos2,
        JTextArea textArea){
    this.s = s; 
    this.ois = ois; 
    this.oos = oos; 
    this.dis = dis2; 
    this.dos = dos2; 
    this.textArea = textArea;
}

public void run(){

    try {
        checkUTF();
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}


public void checkUTF() throws IOException  {
    System.out.println("running to listen");
    while(s.isClosed()==false) {
        String check = null;
        check = dis.readLine();
        if (check!= null) {
            if(check.equals("close")){
                close();
                break;
            }else{
                textArea.append("\n"+check);
                System.out.println("receive message from the server");
            }
        }
    }
}

public void close(){
    System.out.println("closing");
    try {
        s.close();
        dos.close();
        dis.close();
        oos.close();
        ois.close(); 
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

java multithreading server client socks
1个回答
0
投票

我在使用端口和套接字制作聊天服务器时遇到了类似的问题。要解决此问题,请查看是否已在用于从客户端发送消息的按钮中添加了用于启动套接字和端口读取器的所有代码(本例中为“ btnSend”)。之所以会影响客户端接收消息的时间,是因为您必须单击发送按钮以激活程序的接收端。您可以简单地提取代码中启动线程并从按钮操作侦听器接收信息的部分。希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.