java chat server see online accounts

非 Y 不嫁゛ 提交于 2019-12-11 04:51:59

问题


I am implementing a basic chat server on Java. Actually I finished basic things and trying to improve it.

Now I wanna trying on making a list which shows who is online. I have a problem. I get string on JTextPane component and when I press "ENTER" it sends the message but the text cursor goes to lower line. I use setCaretPosition(0); but it didn't work.

You can see the image below and understand the problem.

Here is my server and server thread code;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


public class Server {

    private ServerSocket ss;
    private Socket s;
    Map<Socket,DataOutputStream> list = new HashMap<Socket,DataOutputStream>();

    public Server(int port_number) throws IOException{

        create_Server(port_number);
    }

    public static void main(String[] args) throws IOException {

        int port_number=23;

        new Server(port_number);
    }

    private void create_Server(int port_number) throws IOException{

        ss = new ServerSocket(port_number);

        System.out.println("Server is ready!");

        while(true){

            s=ss.accept();

            System.out.println(s.getLocalAddress().getHostName() + " was connected!");

                        send_con_mes();

            list.put(s,new DataOutputStream(s.getOutputStream()) );

            new ServerThread(s,this).start();
        }

    }

        private void send_con_mes() throws IOException{

                Set<Socket> sckt_list = list.keySet();
        Iterator<Socket> itr = sckt_list.iterator();
                DataOutputStream daos;

                String str;
                Socket sckt;

                while(itr.hasNext()){

                    sckt=itr.next();
                    str = sckt.getLocalAddress().getHostName() + " was connected..." ;

                    daos = list.get(sckt);
                    daos.writeUTF(str);

                }

        }

    public void send_to_All(String msg, Socket socket) throws IOException{

        synchronized(list){

            Set<Socket> sckt_list = list.keySet();
            Iterator<Socket> itr = sckt_list.iterator();
            DataOutputStream daos;

            while(itr.hasNext()){

                Socket sck = itr.next();

                if(sck!=socket){

                    daos = list.get(sck);
                    daos.writeUTF(msg);

                }
            }
        }
    }

    public void remove_Connection(Socket s) throws IOException{

        synchronized(list){

            list.remove(s);
            System.out.println(s.getLocalAddress().getHostName() + " was disconnected!");
            s.close();
        }
    }

}

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


public class ServerThread extends Thread {

    private Socket s;
    private Server srv;

    public ServerThread(Socket s,Server srv){
        this.s = s;
        this.srv = srv;
    }

    @Override
    public void run() {

        String msg;
                DataInputStream dis;

        try {
            dis = new DataInputStream(s.getInputStream());

            while(true){

                msg = dis.readUTF();
                srv.send_to_All(msg, s);

            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally{
            try {
                srv.remove_Connection(s);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

So I guess I must implement the list in server.java but the problem is how can I pass the list and use it in client.java. and here is my client code:

import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Client.java
 *
 * Created on 02.Eyl.2011, 16:46:44
 */
/**
 *
 * @author BURAKTAS
 */
public class Client extends javax.swing.JFrame implements Runnable {

    private DataOutputStream dos;
    private DataInputStream dis;
    private Socket s;
    private String Client_name;
    private String Ip_addr;
    private DefaultListModel listModel=new DefaultListModel();


    /** Creates new form Client */
    public Client() {
        initComponents();
        Screen.setEditable(false);

        acc_list.setVisibleRowCount(6);
        listModel.addElement(Client_name);



        start_Chat();

    }

    @Override
    public void run() {

        try {

            while(true){

            String message = dis.readUTF();
            Screen.append(message + "\n");
            }

        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

    }



    public void start_Chat() {
        try {

            Ip_addr = JOptionPane.showInputDialog("Enter the IP number of the server to connect : ");
            s = new Socket(Ip_addr, 23);

            Client_name = JOptionPane.showInputDialog("Enter your Nickname : ");

            dis = new DataInputStream(s.getInputStream());
            dos = new DataOutputStream(s.getOutputStream());

            new Thread(Client.this).start();

        } catch (UnknownHostException ex) {
            JOptionPane.showMessageDialog(rootPane, "Socket can not connected", "ERROR", JOptionPane.ERROR_MESSAGE);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(rootPane, "Socket can not connected", "ERROR", JOptionPane.ERROR_MESSAGE);
            start_Chat();
        }

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        font_chooser = new javax.swing.JColorChooser();
        jScrollPane1 = new javax.swing.JScrollPane();
        Screen = new javax.swing.JTextArea();
        Send_Button = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        acc_list = new javax.swing.JList();
        disco_button = new javax.swing.JButton();
        jScrollPane3 = new javax.swing.JScrollPane();
        Text_Field = new javax.swing.JTextPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("BrkChat_Server vs 1.0");
        setResizable(false);

        Screen.setColumns(20);
        Screen.setRows(5);
        jScrollPane1.setViewportView(Screen);

        Send_Button.setText("Send");
        Send_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Send_ButtonActionPerformed(evt);
            }
        });

        acc_list.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        acc_list.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        jScrollPane2.setViewportView(acc_list);

        disco_button.setText("Disconnect");
        disco_button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                disco_buttonActionPerformed(evt);
            }
        });

        Text_Field.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR));
        Text_Field.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                Text_FieldKeyPressed(evt);
            }
        });
        jScrollPane3.setViewportView(Text_Field);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 383, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(disco_button, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 108, Short.MAX_VALUE)
                    .addComponent(Send_Button, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 108, Short.MAX_VALUE)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 108, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 286, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 288, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(Send_Button, javax.swing.GroupLayout.DEFAULT_SIZE, 79, Short.MAX_VALUE)
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 76, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(disco_button, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(11, 11, 11))
        );

        pack();
    }// </editor-fold>

private void write(){

            try {

            Text_Field.setCaretPosition(0);
            String str = Text_Field.getText();

            dos.writeUTF(Client_name + " : " + str);
            Screen.append(Client_name + " : " + str + "\n");
            Text_Field.setText("");
        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
}

private void Send_ButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            

    write();

}                                           

private void disco_buttonActionPerformed(java.awt.event.ActionEvent evt) {
        try {
            s.close();
            this.setVisible(false);
            System.exit(0);
        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
}

private void Text_FieldKeyPressed(java.awt.event.KeyEvent evt) {

        if(evt.getKeyCode()==KeyEvent.VK_ENTER){
            write();

        }
}

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Windows".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Client.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Client.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Client.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Client.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {

                new Client().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JTextArea Screen;
    private javax.swing.JButton Send_Button;
    private javax.swing.JTextPane Text_Field;
    private javax.swing.JList acc_list;
    private javax.swing.JButton disco_button;
    private javax.swing.JColorChooser font_chooser;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    // End of variables declaration

}

I appreciated if you can help me. And thanks anyway.


回答1:


One way to implement this would be to implement some event that contains a list of usernames that is sent to all users every time a user connects/disconnects. To keep things simple you could also take a page out of the FTP implementation and use two channels per user - one for the text and another for system commands.

Either way you should basically just serialize the event containing all the necessary information and send that to all clients. Those then basically only have to deserialize it, check what kind of event they have and handle it accordingly. That way you let the Java Serialization API handle all the complicated work - though you can also define your own protocol and use protobuf or something (more efficient; more work).




回答2:


This is due to the fact that you clear the textfield inside the listeners keyPressed method. Thus the key event is still present and the text (in this case a newline) is added afterwards. The quick-and-dirty workaround is to add a evt.consume(); just before your call to write().



来源:https://stackoverflow.com/questions/7295569/java-chat-server-see-online-accounts

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!