当前位置: 首页 > 知识库问答 >
问题:

Java多客户端聊天应用-发送消息问题

丁慈
2023-03-14

我的问题是,我仍然可以在客户端之间发送消息(客户端到客户端),但发送两三次后,消息不再显示给收件人。

因此,基本上每当客户机希望向另一个客户机发送消息时,该消息首先被发送到服务器。但正如您从我的编码中注意到的,我是以对象的形式发送服务器数据的。例如:

send(new ChatMessage(type, sender, content, recipient));

当您发送消息时,类型是“message”。当服务器接收对象时,它检查接收数据及其类型。例如:

ChatMessage cm = (ChatMessage) in[client[id].readObject();
if(cm.type.equals("message"){
  send(findUserThread(toWhom), new ChatMessage("message", sender, content, recipient);

}

如果类型是“message”,那么它会向特定的客户端发送消息

我在客户端使用System.out.println()查看从服务器传入的数据。所以当我尝试发送一些消息,它是工作良好,但然后发送一些消息后,没有显示在我的聊天屏幕。

根据我的逻辑,错误可能是:

JList中的1个选定索引

2客户端[]数组或用户名[]数组

3 ObjectOutputStream和ObjectInputStream

ServerGUI类(服务器端)

package test2;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.*;
import java.util.zip.GZIPOutputStream;
import javax.swing.SwingUtilities;

public class ServerGUI extends JFrame implements ActionListener {

public JList online;
private JTextField ipaddress, textMessage;
private JButton send, start, disconnect;
private JTextArea chatArea;
private JLabel port;
int client[] = new int[100];
private ObjectOutputStream out[] = new ObjectOutputStream[client.length + 1];
private ObjectInputStream in[] = new ObjectInputStream[client.length + 1];
String username[] = new String[client.length + 1];
static String b;
public String nm, usm;
private ServerSocket server;
private Socket connect;
boolean success = true;
int id = 0;
ArrayList<String> UserList = new ArrayList<String>();


public ServerGUI() {
    Container c = getContentPane();
    c.setLayout(new BorderLayout());
    c.setPreferredSize(new Dimension(650, 500));


    JPanel p = new JPanel();
    p.setLayout(new FlowLayout());
    p.setBackground(Color.LIGHT_GRAY);
    p.add(port = new JLabel("Port No"));
    p.add(ipaddress = new JTextField("1500"));
    p.add(start = new JButton("START"));
    p.add(disconnect = new JButton("DISCONNECT"));
    disconnect.setEnabled(false);
    start.setBorderPainted(false);
    start.setBackground(Color.blue);
    start.setForeground(Color.WHITE);
    disconnect.setBorderPainted(false);
    disconnect.setBackground(Color.blue);
    disconnect.setForeground(Color.WHITE);
    ipaddress.setCaretPosition(0);

    JPanel p1 = new JPanel();
    p1.setLayout(new FlowLayout());
    p1.setBackground(Color.LIGHT_GRAY);
    p1.add(chatArea = new JTextArea());

    chatArea.setPreferredSize(new Dimension(300, 350));
    chatArea.setLineWrap(true);
    chatArea.setEditable(false);

    JPanel p2 = new JPanel();
    p2.setLayout(new FlowLayout());
    p2.setBackground(Color.LIGHT_GRAY);
    p2.add(textMessage = new JTextField(20));

    p2.add(send = new JButton("SEND"));
    send.setBackground(Color.blue);
    send.setForeground(Color.WHITE);
    send.setBorderPainted(false);

    start.addActionListener(this);
    send.addActionListener(this);


    c.add(p, BorderLayout.NORTH);
    c.add(p1, BorderLayout.CENTER);
    c.add(p2, BorderLayout.SOUTH);


}
//current time
SimpleDateFormat log = new SimpleDateFormat("HH:mm");
String d = log.format(new Date());

//Start server
public void Start() {

    int portNo = 0;
    try {

        String no = ipaddress.getText();
        portNo = Integer.parseInt(no);
        chatArea.append("Connection to port " + portNo + "...\n");
        server = new ServerSocket(portNo);
        success = true;

    } catch (Exception ex) {
        chatArea.append("Error cannot bind to port \n");
        success = false;
    }

    if (success == true) {
        addClient ob1 = new addClient("RunServer");
        start.setEnabled(false);
        disconnect.setEnabled(true);
    }
}

public class addClient implements Runnable {

    Thread t;

    addClient(String tot) {
        t = new Thread(this, tot);
        t.start();
    }

    public void run() {
        while (true) {
            try {
                try {
                    WaitClient();
                } catch (Exception ex) {
                    break;
                }

                for (int i = 0; i < client.length; i++) {
                    if (client[i] == 0) {
                        client[i] = i + 1;
                        id = i;
                        break;
                    }
                }

                //set stream to send and receive data
                out[client[id]] = new ObjectOutputStream(connect.getOutputStream());
                out[client[id]].flush();
                in[client[id]] = new ObjectInputStream(connect.getInputStream());
                chatArea.append(d + " Client:[" + client[id] + "] : Connected successful \n");
                chatArea.setCaretPosition(chatArea.getText().length());
                //inform user that connection is successfull                    
                ChatMessage cm = (ChatMessage) in[client[id]].readObject(); // read client username
                if(cm.type.equals("login")){
                    chatArea.append("User " +cm.sender + " connected successfully" + "\n" );
                    username[client[id]] = cm.sender;
                    System.out.println(username[0]+ username[1]+ username[2]);
                    send(client[id], new ChatMessage("login", username[client[id]], "user", "SERVER"));
                    sendUserList(cm.sender);
                    Announce("newuser", "SERVER", cm.sender);




                }




                Chat c = new Chat(client[id], "StartChat" + client[id]); // make new thread for every new client 

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


    }

}

public class Chat implements Runnable {

    int id1;
    Chat ob1;
    Thread t;

    Chat(int id1, String info1) {
        this.id1 = id1; // create a thread for client
        t = new Thread(this, info1);
        t.start();
    }

    public void run() {
     boolean running = true;
       while(running){
            try {
                ChatMessage cm = (ChatMessage) in[client[id]].readObject(); // read client username
                if(cm.type.equals("message")){

                         send(findUserThread(cm.recipient), new ChatMessage(cm.type, cm.sender, cm.content, cm.recipient));


                }

            } catch (Exception e) {

            }
       }

    }
}




//wait for connection, then display connection information
private void WaitClient() throws IOException {

    chatArea.append(d + " : Waiting for connection... \n");
    connect = server.accept();

    chatArea.append(d + " : Now connected to " + connect.getInetAddress().getHostName() + "\n");
}

//send message to specific user
public void sendUser(int number, String info) {

    try {
        out[number].writeObject(info);
        out[number].flush();
    } catch (Exception e) {
    }

}

public void sendServer(String por) {
    for (int i = 0; i < client.length; i++) // for loop trying to send message from server to all clients 
    {
        if (client[i] != 0) // this line stop server to send messages to offline clients
        {
            try {
                out[i + 1].writeObject(por);
                out[i + 1].flush();
            } catch (Exception e) {
            }
        }
    }
}

public void Announce(String type, String sender, String content){

    ChatMessage cm = new ChatMessage(type, sender, content, "All");
    for(int i = 0; i < id; i++){
        send(client[i], cm);
    }
}



public void send(int number, ChatMessage cm) {

    try {
        out[number].writeObject(cm);
        out[number].flush();
    } catch (Exception e) {
    }

}





void sendAll(int num, String por) {
    for (int i = 0; i < client.length; i++) // for loop trying to send message from server to all clients 
    {
        if (client[i] != 0) // this line stop server to send messages to offline clients (if "clientNiz[X] = 0" don't try to send him message, because that slot is empty)
        {
            if (num != i + 1) // don't repeat messages (when for ex. client_1 send message to all clients, this line stop server to send same message back to client_1)
            {
                try {
                    out[i + 1].writeObject(por);
                    out[i + 1].flush();
                } catch (Exception e) {
                }
            }
        }
    }
}

public void sendUserList(String toWhom){
    for(int i = 0; i <= id; i++){
        send(findUserThread(toWhom), new ChatMessage("newuser", "SERVER", username[client[i]], toWhom));
    }
}

public int findUserThread(String usr){
    for(int i = 0; i <= id; i++){
        if(username[client[i]].equals(usr)){
            return client[i];
        }

    }
    return -1;
}

  private int findClient(int num){  
    for (int i = 0; i <= id; i++){
        if (client[i] == (num+1)){
                return i;
            }
}
return -1;
}





public void actionPerformed(ActionEvent e) {
    if (e.getSource() == send) {
        //current time

        String s1 = textMessage.getText();
        send(client[id], new ChatMessage("message", "admin", s1, "client"));
        chatArea.append("Administrator: " + s1 + "\n");


    } else if (e.getSource() == start) {
        Start();
    }
    if (e.getSource() == disconnect) {

        try {
            server.close();
        } catch (Exception ex) {
        }

        for (int i = 0; i < client.length; i++) {
            try {
                in[i].close();
                out[i].close();
            } catch (Exception ex) {
            }
        }
        chatArea.append("Server is disconnected\n");
        start.setEnabled(true);
        disconnect.setEnabled(false);
    }
}
}

MainGUI类(客户端)

package test2;

import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;


public class MainGUI extends javax.swing.JFrame {

public MainGUI() {
    initComponents();





}

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

    jButton1 = new javax.swing.JButton();
    jButton3 = new javax.swing.JButton();
    start = new javax.swing.JButton();
    jLabel2 = new javax.swing.JLabel();
    textMessage = new javax.swing.JTextField();
    jScrollPane2 = new javax.swing.JScrollPane();
    chatArea = new javax.swing.JTextArea();
    usernm = new javax.swing.JTextField();
    jLabel1 = new javax.swing.JLabel();
    send = new javax.swing.JButton();
    upload = new javax.swing.JButton();
    filename = new javax.swing.JTextField();
    jScrollPane1 = new javax.swing.JScrollPane();
    online = new javax.swing.JList();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle("ICARE ");
    setFocusable(false);
    setPreferredSize(new java.awt.Dimension(840, 650));
    setResizable(false);
    getContentPane().setLayout(null);

    jButton1.setText("Video Call");
    getContentPane().add(jButton1);
    jButton1.setBounds(270, 10, 100, 30);

    jButton3.setText("Send");
    jButton3.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton3ActionPerformed(evt);
        }
    });
    getContentPane().add(jButton3);
    jButton3.setBounds(690, 100, 100, 30);

    start.setBackground(new java.awt.Color(51, 51, 255));
    start.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
    start.setForeground(new java.awt.Color(255, 255, 255));
    start.setText("Start");
    start.setBorder(null);
    start.setBorderPainted(false);
    start.setRequestFocusEnabled(false);
    start.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            startActionPerformed(evt);
        }
    });
    getContentPane().add(start);
    start.setBounds(630, 50, 90, 40);
    getContentPane().add(jLabel2);
    jLabel2.setBounds(0, 0, 820, 0);
    getContentPane().add(textMessage);
    textMessage.setBounds(270, 450, 420, 70);

    chatArea.setColumns(20);
    chatArea.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N
    chatArea.setRows(5);
    jScrollPane2.setViewportView(chatArea);

    getContentPane().add(jScrollPane2);
    jScrollPane2.setBounds(270, 140, 520, 300);
    getContentPane().add(usernm);
    usernm.setBounds(450, 60, 170, 30);

    jLabel1.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
    jLabel1.setText("Enter your nickname:");
    getContentPane().add(jLabel1);
    jLabel1.setBounds(270, 60, 150, 30);

    send.setBackground(new java.awt.Color(51, 51, 255));
    send.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
    send.setForeground(new java.awt.Color(255, 255, 255));
    send.setText("Send");
    send.setBorder(null);
    send.setBorderPainted(false);
    send.setRequestFocusEnabled(false);
    send.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            sendActionPerformed(evt);
        }
    });
    getContentPane().add(send);
    send.setBounds(700, 470, 90, 40);

    upload.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N
    upload.setText("+");
    upload.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            uploadActionPerformed(evt);
        }
    });
    getContentPane().add(upload);
    upload.setBounds(633, 100, 50, 30);
    getContentPane().add(filename);
    filename.setBounds(270, 100, 350, 30);

    jScrollPane1.setViewportView(online);

    getContentPane().add(jScrollPane1);
    jScrollPane1.setBounds(30, 20, 220, 500);

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

private void startActionPerformed(java.awt.event.ActionEvent evt) {                                      
    Start();


}                                     

private void sendActionPerformed(java.awt.event.ActionEvent evt) {                                     
    // TODO add your handling code here:
    String z = textMessage.getText();
    String target = online.getSelectedValue().toString();
    chatArea.append("[ " + usernm.getText() + " ] : " + z + "\n");

    send(new ChatMessage("message", usernm.getText(), z, target));
    textMessage.setText("");         


}                                    

private void uploadActionPerformed(java.awt.event.ActionEvent evt) {                                       
    // TODO add your handling code here:
    //Create a file chooser
//In response to a button click:
JFileChooser fileChooser = new JFileChooser();
    fileChooser.showDialog(this, "Select File");
    file = fileChooser.getSelectedFile();

    if(file != null){
        if(!file.getName().isEmpty()){
            String str;

            if(filename.getText().length() > 30){
                String t = file.getPath();
                str = t.substring(0, 20) + " [...] " + t.substring(t.length() - 20, t.length());
            }
            else{
                str = file.getPath();
            }
            filename.setText(str);
        }
    }
}                                      

private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    // TODO add your handling code here:
      long size = file.length();
        if(size < 120 * 1024 * 1024){
            sendUser("download");


        }
        else{
            chatArea.append("File is size too large\n");
        }
}                                        

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 ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(MainGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(MainGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(MainGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(MainGUI.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 MainGUI().setVisible(true);

        }
    });
}
// Variables declaration - do not modify
public javax.swing.JTextArea chatArea;
private javax.swing.JTextField filename;
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton3;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
public javax.swing.JList online;
private javax.swing.JButton send;
private javax.swing.JButton start;
private javax.swing.JTextField textMessage;
private javax.swing.JButton upload;
private javax.swing.JTextField usernm;
// End of variables declaration


private ObjectOutputStream out;
private ObjectInputStream in;
static String b; //variable for message
private Socket join;
boolean success = true;
private String serverIP = "127.0.0.1"; //set IP Address
ArrayList<String> userlist = new ArrayList<String>(); //ArrayList to store online users
//current time
SimpleDateFormat log = new SimpleDateFormat("HH:mm");
String d = log.format(new Date());
public File file;
public DefaultListModel model = new DefaultListModel();



//Start client program
public void Start() {

    try {

        start.setEnabled(false);
        chatArea.append(d + " : Attempting connection... \n");

        join = new Socket(serverIP, 10500);
        chatArea.append(d + " : Connected to - " + join.getInetAddress().getHostName() + "\n");

        success = true;

    } catch (Exception ex) {
        chatArea.append("Error cannot bind to port \n");            
        success = false;
    }

    if (success == true) {

        ClientThread ct = new ClientThread();


    }
}

class ClientThread implements Runnable {

    ClientThread ct;
    Thread t;

    ClientThread() {
        t = new Thread(this, "RunClient");
        t.start();

    }

    public void run() {
        try {
            try {
                out = new ObjectOutputStream(join.getOutputStream());
                out.flush();
                in = new ObjectInputStream(join.getInputStream());

                send(new ChatMessage("login", usernm.getText(), "password", "SERVER"));                
            } catch (Exception e) {   }



            CThread c1 = new CThread();


        } catch (Exception ex) {   }
    }
}

class CThread implements Runnable {

    CThread ob1;
    Thread t;

    CThread() {
        t = new Thread(this, "Message");
        t.start();
    }


    public void run() {
        boolean running = true;
        try {
            while(running){
                try {

                    ChatMessage cm = (ChatMessage) in.readObject();
                    System.out.println("Incoming :" + cm.toString());
                    if(cm.type.equals("login")){
                     chatArea.append(cm.sender + " is online" + "\n");
                    }else if(cm.type.equals("message")){                           
                        if(cm.recipient.equals(usernm.getText())){
                                 chatArea.append("[ "+cm.sender +" ] : " + cm.content + "\n");

                        }
                   }else if(cm.type.equals("newuser")){

                        online.setModel(model);
                        model.addElement(cm.content);
                    }

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





void sendUser(String por) {
    try {
        out.writeObject(por);
        out.flush();
    } catch (Exception e) {
    }
}

void send(ChatMessage cm){
    try {
        out.writeObject(cm);
        out.flush();
    } catch (Exception e) {
    }

}


}

ChatMessage类

package test2;

import java.io.Serializable;

public class ChatMessage implements Serializable{

private static final long serialVersionUID = 1L;
public String type, sender, content, recipient;

public ChatMessage(String type, String sender, String content, String recipient){
    this.type = type; this.sender = sender; this.content = content; this.recipient = recipient;
}

@Override
public String toString(){
    return "{type='"+type+"', sender='"+sender+"', content='"+content+"', recipient='"+recipient+"'}";
}
}

运行ServerGUI的ServerTest

公共类ServerTest{public static void main(String args[]){

    ServerGUI m = new ServerGUI();

    m.setTitle("Server");

    m.setVisible(true);

    m.pack();

    //to make to the center of the screen

    m.setLocationRelativeTo(null);


}
}

共有1个答案

公冶高峯
2023-03-14
  • Java的类应该以大写开头。例如:ServerGUI而不是代码中的AddClient
  • 类表示对象。或物体的“类”。例如carservergui,但不包括addclient。什么是新addClient()?那真的是一个物体吗?
  • 变量名应该有重要的名称(如果可能的话)。例如Car limousine=new Car(4,color.black)而不是addClient ob1=new addClient(“runserver”)ob1是什么意思?
  • 评论是读者的新鲜空气。请使用评论。例如://我们将服务器表示为具有管理权限的特殊用户
  • 方法名称ir Java不应以大写开头。这是一个糟糕的示例:private void WaitClient()抛出IOException
  • 缩进和空行。我不知道是部分还是完全是您的错误,但代码缩进不良,块内有空行(不只是一个或两个块,也不用作分隔符),并且缺少空格(if(cm.type.equals(“login”)){)
  • StackOverflow不适合解决您的问题。在这里人们会问一些具体的问题。你的不是一个具体的问题,更多的是一个“我的程序不工作”的问题。

总之:您的代码很难阅读和理解。看来您是Java的新手,所以请从简单易用的示例开始,使用Eclipse或Netbeans这样的Java IDE并慢慢来!你一周内学不到Java,耐心点。

抱歉,如果我太诚实了,但我就是这么想的(可能也是这里没有人帮你的原因之一)。

 类似资料:
  • 如何在聊天客户端发送媒体消息?我使用的是JS SDK,基于教程https://www.twilio.com/docs/api/chat/guides/media-support,但是出现了错误。我使用的方法如下所示: 错误消息:

  • Twilio布道者们好, 我们使用Twilio模块,可编程聊天,并使用Javascript客户端和Twilio.api,C#服务器API。 我们希望用户看到特定信道的信道和消息,但需要有条件地阻止他们发送消息。 我们可以禁用UI元素,但智能用户仍然能够访问Twilio客户端,并发送消息。

  • 我一直在努力通过Smack和Openfire服务器与XMPP聊天。我的问题如下: 每当一个用户向另一个用户发送消息时,该消息就会在另一个用户处正确接收。但是任何回复都不会出现在第一条消息的发件人处。因此,用户1成功地发送给用户2。然后,用户2无法向用户1发送任何回复。另一方面,如果我重新启动并让用户再次登录,则用户2可以发送给用户1,但反之亦然。 我想说的是,只有聊天的发起者才能发送消息,接收者不

  • 我对python有点陌生,这是我第一次使用套接字,我试图制作一个具有客户端和服务器的应用程序,用户可以在客户端中输入,它将被发送到服务器,然后将其发送给所有其他客户端。我已经将其设置为工作状态,但每当我尝试发送第二条消息时,我总是收到一个错误错误:[Errno 10058]发送或接收数据的请求被禁止,因为套接字已经在之前的关闭调用中关闭了该方向。我如何才能做到这一点? 尝试在启动新套接字或发送新消

  • 我正在尝试使用node.js、socket.io和express制作一个简单的聊天应用程序。但是,如果我单击main.jade文件中的send按钮,页面会刷新,并且不会出现任何消息。我在Firebug中也遇到这个错误: 加载页面时,与ws:/127.0.0.1:3000/socket.io/?eio=2&transport=websocket&sid=d_hnmpdxhed-j7lraaah的连接