我在聊天中创建了一个资源,以便聊天用户可以创建群组并加入这些群组并发送消息,并且只有群组中的人会收到它,但是当群组中的某个人向群组中的每个人发送消息时,每个人收到它,包括谁发送的。我希望发送消息的人不要收到它。做了几次测试,发现问题出在ServerService类的sendGroup方法上。我尝试通过多种方式解决这个问题,但没有成功。
客户端框架:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;
import servidor.ChatMessage;
import servidor.ChatMessage.Action;
import servidor.ServerService;
public class ClientFrame extends javax.swing.JFrame {
private Socket socket;
private ChatMessage message;
private ClienteService service;
public ClientFrame() throws IOException {
initComponents();
}
private class ListenerSocket implements Runnable{
private ObjectInputStream input;
public ListenerSocket(Socket socket) throws IOException{
this.input = new ObjectInputStream(socket.getInputStream());
}
@Override
public void run() {
try {
while((message = (ChatMessage) input.readObject()) != null){
Action action = message.getAction();
if(action.equals(action.CONNECT)){
connected(message);
}else if(action.equals(action.SEND_ONE)){
receive(message);
}else if(action.equals(action.USERS_ONLINE)){
RefreshOnlines(message);
}else if(action.equals(action.ONLINE_GROUPS)){
RefreshOnlinesGroups(message);
}
}
} catch (IOException ex) {
dispose();
Logger.getLogger(ServerService.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(ServerService.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void connected(ChatMessage message){
if(message.getText().equals("NO")){
txtName.setText("");
JOptionPane.showMessageDialog(null, "Connection not made. \n Try another name.");
return;
}
message = message;
btnConnect.setEnabled(false);
txtName.setEditable(false);
txtAreaSend.setEnabled(true);
txtAreaReceive.setEnabled(true);
txtNewGroup.setEnabled(true);
btnCreateGroup.setEnabled(true);
btnEnterGroup.setEnabled(true);
btnMessageGroup.setEnabled(true);
btnUpdateGroup.setEnabled(true);
JOptionPane.showMessageDialog(null, "Connection successful");
}
private void receive(ChatMessage message){
txtAreaReceive.append(message.getName() +" it says: "+ message.getText()+ "\n");
}
private void RefreshOnlinesGroups(ChatMessage message){
System.out.println(message.getSetOnlinesGroups().toString());
Set<String> namesGroups = message.getSetOnlinesGroups();
String[] arrayGrupo = (String[])namesGroups.toArray(new String [namesGroups.size()]);
listGroups.setListData(arrayGrupo);
listGroups.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
listGroups.setLayoutOrientation(JList.VERTICAL);
}
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jScrollPane5 = new javax.swing.JScrollPane();
jList1 = new javax.swing.JList<>();
jPanel1 = new javax.swing.JPanel();
txtName = new javax.swing.JTextField();
btnConnect = new javax.swing.JButton();
jPanel2 = new javax.swing.JPanel();
jScrollPane4 = new javax.swing.JScrollPane();
listOnlines = new javax.swing.JList<>();
jScrollPane6 = new javax.swing.JScrollPane();
listGroups = new javax.swing.JList<>();
btnCreateGroup = new javax.swing.JButton();
txtNewGroup = new javax.swing.JTextField();
btnEnterGroup = new javax.swing.JButton();
btnUpdateGroup = new javax.swing.JButton();
jPanel3 = new javax.swing.JPanel();
jScrollPane2 = new javax.swing.JScrollPane();
txtAreaReceive = new javax.swing.JTextArea();
jScrollPane3 = new javax.swing.JScrollPane();
txtAreaSend = new javax.swing.JTextArea();
btnMessageGroup = new javax.swing.JButton();
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1);
private void txtNameActionPerformed(java.awt.event.ActionEvent evt) {
}
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {
String name = this.txtName.getText();
if(!name.isEmpty()){
this.message = new ChatMessage();
this.message.setAction(Action.CONNECT);
this.message.setName(name);
this.service = new ClienteService();
try {
this.socket = this.service.connect();
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Server not initialized");
Logger.getLogger(ClientFrame.class.getName()).log(Level.SEVERE, null, ex);
}
try {
new Thread(new ListenerSocket(this.socket)).start();
} catch (IOException ex) {
Logger.getLogger(ClientFrame.class.getName()).log(Level.SEVERE, null, ex);
}
try {
setTitle(name);
this.service.send(message);
} catch (IOException ex) {
Logger.getLogger(ClientFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void btnCreateGroupActionPerformed(java.awt.event.ActionEvent evt) {
this.message = new ChatMessage();
String newGroup = this.txtNewGroup.getText();
if(!newGroup.isEmpty()){
this.message.setAction(Action.NEW_GROUP);
this.message.setGroupReserved(newGroup);
try {
this.service.send(this.message);
} catch (IOException ex) {
Logger.getLogger(ClientFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}else{
JOptionPane.showMessageDialog(null, "Enter a name to create a group");
}
}
private void btnEnterGroupActionPerformed(java.awt.event.ActionEvent evt) {
String nome = this.txtName.getText();
this.message = new ChatMessage();
if(this.listGroups.getSelectedIndex() > -1){
this.message.setAction(Action.ENTER_GROUP);
this.message.setName(nome);
this.message.setGroupReserved(this.listGroups.getSelectedValue());
try {
this.service.send(this.message);
JOptionPane.showMessageDialog(null, "You joined the group");
} catch (IOException ex) {
Logger.getLogger(ClientFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}else{
JOptionPane.showMessageDialog(null, "Select a group to join");
}
listGroups.clearSelection();
}
private void btnMessageGroupActionPerformed(java.awt.event.ActionEvent evt) {
String text = this.txtAreaSend.getText();
String name = this.txtName.getText();
this.message = new ChatMessage();
if(this.listGroups.getSelectedIndex() > -1){
this.message.setGroupReserved(this.listGroups.getSelectedValue());
this.message.setAction(Action.SEND_GROUP);
this.listGroups.clearSelection();
if(!text.isEmpty()){
this.message.setName(name);
this.message.setText(text);
this.txtAreaReceive.append("You said: " + text + "\n");
try {
this.service.send(this.message);
}catch (IOException ex) {
Logger.getLogger(ClientFrame.class.getName()).log(Level.SEVERE, null, ex);
}
this.txtAreaSend.setText("");
}
}else{
JOptionPane.showMessageDialog(null, ("Select a group to send the message"));
}
}
private void btnUpdateGroupActionPerformed(java.awt.event.ActionEvent evt) {
this.message = new ChatMessage();
this.message.setAction(Action.ONLINE_GROUPS);
try {
this.service.send(this.message);
} catch (IOException ex) {
Logger.getLogger(ClientFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Variables declaration - do not modify
private static javax.swing.JButton btnConnect;
private javax.swing.JButton btnCreateGroup;
private javax.swing.JButton btnEnterGroup;
private javax.swing.JButton btnMessageGroup;
private javax.swing.JButton btnUpdateGroup;
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JList<String> jList1;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JScrollPane jScrollPane3;
private javax.swing.JScrollPane jScrollPane4;
private javax.swing.JScrollPane jScrollPane5;
private javax.swing.JScrollPane jScrollPane6;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JList<String> listGroups;
private javax.swing.JList<String> listOnlines;
private javax.swing.JTextArea txtAreaReceive;
private javax.swing.JTextArea txtAreaSend;
private javax.swing.JTextField txtName;
public static javax.swing.JTextField txtNewGroup;
// End of variables declaration
}
服务服务:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import servidor.ChatMessage.Action;
public class ServerService {
private ServerSocket serverSocket;
private Socket socket;
public static Map<String, ObjectOutputStream> mapOnlines = new HashMap<String, ObjectOutputStream>();
private static Map<String, ObjectOutputStream> mapGroup = new HashMap<String, ObjectOutputStream>();
private Map<String, String> mapUserGroup = new HashMap<String, String>();
public ServerService() throws IOException{
try {
serverSocket = new ServerSocket(5555);
System.out.println("Server ON");
} catch (IOException ex) {
Logger.getLogger(ServerService.class.getName()).log(Level.SEVERE, null, ex);
}
while(true){
socket = serverSocket.accept();
new Thread(new ListenerSocket(socket)).start();
}
}
private class ListenerSocket implements Runnable {
private ObjectOutputStream output;
private ObjectInputStream input;
public ListenerSocket(Socket socket) throws IOException{
this.output = new ObjectOutputStream(socket.getOutputStream());
this.input = new ObjectInputStream(socket.getInputStream());
}
public void run() {
ChatMessage message = null;
sendOnlinesGroups();
try {
while((message = (ChatMessage) input.readObject()) != null){
Action action = message.getAction();
if(action.equals(action.CONNECT)){
boolean isConnect = connect(message, output);
if(isConnect){
mapOnlines.put(message.getName(), output);
sendOnlines();
}
}else if(action.equals(action.NEW_GROUP)){
if(mapGroup.containsKey(message.getGroupReserved())){
JOptionPane.showMessageDialog(null, "A group with that name already exists");
}else{
JOptionPane.showMessageDialog(null, "Successfully created group");
mapGroup.put(message.getGroupReserved(), output);
sendOnlinesGroups();
}
}else if(action.equals(action.ENTER_GROUP)){
mapUserGroup.put(message.getName(),message.getGroupReserved());
}else if(action.equals(action.SEND_ONE)){//Envio de mensagem reservada
sendOne(message);
}else if(action.equals(action.SEND_GROUP)){
sendGroup(message);
}else if(action.equals(action.USERS_ONLINE)){//Lista de usuários online
}else if(action.equals(action.ONLINE_GROUPS)){
mapGroup.put("", output);
sendOnlinesGroups();
}
}
} catch (IOException ex) {
ChatMessage cm = new ChatMessage();
cm.setName(message.getName());
sendOnlines();
Logger.getLogger(ServerService.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex){
Logger.getLogger(ServerService.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private boolean connect(ChatMessage message, ObjectOutputStream output) throws IOException{
if(mapOnlines.size()== 0){
message.setText("YES");
send(message, output);
return true;
}
if(mapOnlines.containsKey(message.getName())){
message.setText("NO");
send(message,output);
return false;
}else{
message.setText("YES");
send(message, output);
return true;
}
}
private void send(ChatMessage message, ObjectOutputStream output) throws IOException{
output.writeObject(message);
}
private void sendOne(ChatMessage message) throws IOException{
for (Map.Entry<String, ObjectOutputStream> kv : mapOnlines.entrySet()){
if(kv.getKey().equals(message.getNameReserved())){
kv.getValue().writeObject(message);
}
}
}
private void sendGroup(ChatMessage message) {
for (Map.Entry<String, ObjectOutputStream> kv : mapGroup.entrySet()) {
if (kv.getKey().equals(message.getGroupReserved())) {
String group = kv.getKey();
Set<String> keys = mapUserGroup.keySet();
for (String key : keys) {
if (mapUserGroup.get(key).equals(group)) {
}
message.setAction(Action.SEND_ONE);
try {
mapOnlines.get(key).writeObject(message);
} catch (IOException ex) {
Logger.getLogger(ServerService.class.getName()).log(Level.SEVERE, null, ex);
}}}}}
private void sendOnlinesGroups(){
Set<String> setNamesGroups = new HashSet<String>();
for(Map.Entry<String, ObjectOutputStream> kv : mapGroup.entrySet()){
setNamesGroups.add(kv.getKey());
}
ChatMessage message = new ChatMessage();
message.setAction(Action.ONLINE_GROUPS);
message.setSetOnlinesGroups(setNamesGroups);
for (Map.Entry<String, ObjectOutputStream> kv : mapGroup.entrySet()){
message.setGroupReserved(kv.getKey());
try {
kv.getValue().writeObject(message);
} catch (IOException ex) {
Logger.getLogger(ServerService.class.getName()).log(Level.SEVERE, null, ex);
}}}
public static boolean createGroup(){
ChatMessage message = new ChatMessage();
if(mapGroup.containsKey(message.getGroupReserved())){
JOptionPane.showMessageDialog(null, "A group with that name already exists");
return false;
}else{
JOptionPane.showMessageDialog(null, "Successfully created group");
return true;
}}}
聊天消息:
public class ChatMessage implements Serializable{
private Set<String> setOnlinesGroups = new HashSet<String>();
private Set<String> setOnlines = new HashSet<String>();
private Set<String> setOnlinesPrivate = new HashSet<String>();
private Action action;
public Action getAction() {
return action;
}
public void setAction(Action action) {
this.action = action;
}
public String getGroupReserved() {
return groupReserved;
}
public void setGroupReserved(String groupReserved) {
this.groupReserved = groupReserved;
}
public enum Action {
CONNECT,SEND_ONE, USERS_ONLINE,ONLINE_GROUPS,NEW_GROUP,ENTER_GROUP,SEND_GROUP,
}
}