失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > socket聊天室实现-群聊 私聊 好友列表 完整版

socket聊天室实现-群聊 私聊 好友列表 完整版

时间:2021-09-22 03:14:12

相关推荐

socket聊天室实现-群聊 私聊 好友列表 完整版

效果图

登录。好友上线,下线均提示。

点击好友列表所有人,发送消息,既为群聊

点击好友列表,好友名字,既为选中此好友进行私聊

服务器端代码

ChatRoomServer

package sram.server;import java.io.IOException;import .ServerSocket;import .Socket;import java.util.HashMap;import sram.thread.ChatRoomServerReaderThread;import sram.user.User;public class ChatRoomServer {private ServerSocket ss;public static HashMap<User, Socket> online = new HashMap<User, Socket>(); public ChatRoomServer(){try {ss = new ServerSocket(6666);System.out.println("服务器已经开启,等待客户端...");while(true){Socket s = ss.accept();new Thread(new ChatRoomServerReaderThread(s)).start();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static void main(String[] args) {new ChatRoomServer();}}

1234567891011121314151617181922232425262728

ChatRoomServerReaderThread

package sram.thread;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import .Socket;import java.util.ArrayList;import java.util.List;import java.util.Set;import sram.server.ChatRoomServer;import sram.user.Message;import sram.user.User;import sram.util.SendMessageUtil;import net.sf.json.JSONArray;import net.sf.json.JSONObject;public class ChatRoomServerReaderThread implements Runnable {private Socket s;private BufferedReader br;private PrintWriter pw;private Message message;public ChatRoomServerReaderThread(Socket s) throws IOException {this.s = s;br = new BufferedReader(new InputStreamReader(s.getInputStream()));pw = new PrintWriter(s.getOutputStream(),true);}@Overridepublic void run() {String str = null;try {while((str = br.readLine())!=null){message = new Message(); //返回的消息。System.out.println("发过来的消息是:"+str);Message msg = (Message) JSONObject.toBean(JSONObject.fromObject(str), Message.class);switch (msg.getType()) {case 1: //处理登录消息。User loginUser = msg.getFromUser();if(ChatRoomServer.online.containsKey(loginUser)){//用户名已经存在,不能登录message.setType(11);pw.println(JSONObject.fromObject(message).toString());}else{//用户名未存在,可以登录,返回可以登录的消息//获取所有用户List<User> users = new ArrayList<User>(ChatRoomServer.online.keySet());//List转化为JSON字符串message.setMessage(JSONArray.fromObject(users).toString());message.setType(10);ChatRoomServer.online.put(loginUser, s);pw.println(JSONObject.fromObject(message).toString());//用户登录成功后,系统发送系统消息给每个用户,告诉所有用户 XXX上线了。message.setType(4);message.setFromUser(loginUser);//调用群发方法,群发消息给所有用户。SendMessageUtil.sendMessage(ChatRoomServer.online, message);}break;case 3:User out = msg.getFromUser();ChatRoomServer.online.remove(out);message.setType(5); message.setFromUser(out);SendMessageUtil.sendMessage(ChatRoomServer.online, message);break;case 20: //处理私聊消息User toUser = msg.getToUser();Socket s = ChatRoomServer.online.get(toUser);PrintWriter pw = new PrintWriter(s.getOutputStream(),true);msg.setType(22);pw.println(JSONObject.fromObject(msg).toString());break;case 21: //处理群聊消息msg.setType(23);SendMessageUtil.sendMessage(ChatRoomServer.online,msg);break;}if(msg.getType()==3){break;}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

123456789101112131415161718192223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495

Message

package sram.user;//用来描述发送消息的类。 1登陆 2聊天 3退出 4系统消息等public class Message {private String message; //发送消息内容private int type; //发送消息类型private User fromUser; //来源自谁的消息private User toUser; //发送给谁public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public int getType() {return type;}public void setType(int type) {this.type = type;}public User getFromUser() {return fromUser;}public void setFromUser(User fromUser) {this.fromUser = fromUser;}public User getToUser() {return toUser;}public void setToUser(User toUser) {this.toUser = toUser;}}

1234567891011121314151617181922232425262728293031323334

User

package sram.user;//用户实体类。登陆成功后,可以被保存在服务器端。public class User {private String username; //用户名,唯一的标识private String nickname;//用户自定义的网络名称public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname;}public User(String username, String nickname) {this.username = username;this.nickname = nickname;}public User() {}@Overridepublic int hashCode() {// TODO Auto-generated method stubreturn 0;}@Overridepublic boolean equals(Object obj) {User user = (User)obj;return this.username.equals(user.username);}}

12345678910111213141516171819222324252627282930313233343536

SendMessageUtil

package sram.util;import java.io.IOException;import java.io.PrintWriter;import .Socket;import java.util.Map;import java.util.Set;import net.sf.json.JSONObject;import sram.user.Message;import sram.user.User;public class SendMessageUtil {//群发的方法public static void sendMessage(Map<User, Socket> online,Message message) throws IOException{Set<User> users = online.keySet();for(User user :users){Socket s = online.get(user);PrintWriter pw = new PrintWriter(s.getOutputStream(),true);pw.println(JSONObject.fromObject(message).toString());}}}

12345678910111213141516171819222324

客户端代码

ClientFrame

package sram.frame;import java.awt.BorderLayout;import java.awt.ScrollPane;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.IOException;import java.io.PrintWriter;import .Socket;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JScrollBar;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;import javax.swing.JTree;import javax.swing.border.Border;import javax.swing.border.TitledBorder;import javax.swing.tree.DefaultMutableTreeNode;import javax.swing.tree.DefaultTreeModel;import net.sf.json.JSONObject;import sram.user.Message;import sram.user.User;public class ClientFrame {private JFrame frame; //主窗口private JTextArea area; //显示消息的文本域private JTextField text; //输入消息的文本框private JButton btnSend; //发送消息的按钮private JPanel p1,p2,p3; //布局使用的面板private TitledBorder b1,b2,b3;//好友列表使用JTree显示private JTree tree;private DefaultMutableTreeNode root;// 根节点private DefaultTreeModel model; //树模型private User user;private Socket socket;private PrintWriter pw;private User toUser = new User("All","所有人");private List<User> friends;public DefaultMutableTreeNode getRoot() {return root;}public void setRoot(DefaultMutableTreeNode root) {this.root = root;}public DefaultTreeModel getModel() {return model;}public void setModel(DefaultTreeModel model) {this.model = model;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}public JTextArea getArea() {return area;}public void setArea(JTextArea area) {this.area = area;}public ClientFrame(User user,Socket socket,List<User> friends){this.user = user;//******************************************************this.socket = socket;//**************************************************this.friends = friends;//************************************************//调用init()方法初始化界面init();listener();}//初始化方法显示界面public void init(){//初始化对象**********************************************try {pw = new PrintWriter(socket.getOutputStream(),true);} catch (IOException e) {e.printStackTrace();}frame = new JFrame("当前用户:["+user.getNickname()+"("+user.getUsername()+")"+"]");area = new JTextArea();area.setEditable(false);area.setLineWrap(true);text = new JTextField(20);root = new DefaultMutableTreeNode("我的好友");model = new DefaultTreeModel(root);model.insertNodeInto(new DefaultMutableTreeNode(new User("All", "所有人")), root,root.getChildCount());//************************************************************************************if(friends!=null && friends.size()>0){for(User userf : friends){model.insertNodeInto(new DefaultMutableTreeNode(userf), root,root.getChildCount());}}//************************************************************************************tree = new JTree(model);//启用折叠显示tree.setShowsRootHandles(true);btnSend = new JButton("发送");b1 = new TitledBorder("好友列表");b2 = new TitledBorder("消息显示");b3 = new TitledBorder("发送消息");p1 = new JPanel(); //右边的面板,用来显示好友列表p2 = new JPanel(); //中间的面板,用来显示JTextAreap3 = new JPanel(); //下边的面板,用来显示文本输入框和发送按钮p1.setLayout(new BorderLayout());p2.setLayout(new BorderLayout());p1.setBorder(b1);p2.setBorder(b2);p3.setBorder(b3);p1.add(new JScrollPane(tree));p2.add(new JScrollPane(area,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),BorderLayout.CENTER);p3.add(text);p3.add(btnSend);p2.add(p3,BorderLayout.SOUTH);frame.add(p1,BorderLayout.WEST);frame.add(p2,BorderLayout.CENTER);frame.setResizable(false);frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);frame.setSize(500, 450);frame.setVisible(true);}public void listener(){frame.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {int i = JOptionPane.showConfirmDialog(null, "您确定要退出聊天室?");if(i == JOptionPane.OK_OPTION){Message message = new Message();message.setType(3); //退出消息message.setFromUser(user);pw.println(JSONObject.fromObject(message).toString());try {Thread.sleep(100);System.exit(0);} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}});tree.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {if(tree.getSelectionPath()!=null && tree.getSelectionPath().getParentPath()!=null){//获取点击节点的行数//*********************************************int i = tree.getLeadSelectionRow();DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(i-1);toUser = (User) node.getUserObject();frame.setTitle("当前用户:["+user.getNickname()+"("+user.getUsername()+")"+"] 和 ["+toUser.getNickname()+"("+toUser.getUsername()+")"+"]的聊天");}}});btnSend.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//私聊 群聊Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String msg = text.getText();if(msg!=null && !msg.equals("")){Message message = new Message();message.setMessage(msg);message.setFromUser(user);text.setText("");if(toUser!=null){if(toUser.getUsername().equals("All")){message.setType(21);area.append("【群聊】"+user.getNickname()+"("+user.getUsername()+") "+sdf.format(date)+" 说:");area.append(msg+"\r\n");}else{message.setType(20);area.append("【私聊】"+user.getNickname()+"("+user.getUsername()+") "+sdf.format(date)+" 说:");area.append(msg+"\r\n");}}message.setToUser(toUser);pw.println(JSONObject.fromObject(message).toString());}}});}public static void main(String[] args) {//new ClientFrame(new User(),new Socket());}}

123456789101112131415161718192223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920002203204205206207208209210211212

LoginFrame

package sram.frame;import java.awt.Dimension;import java.awt.GridLayout;import java.awt.Toolkit;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import .Socket;import .UnknownHostException;import java.util.List;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JTextField;import net.sf.json.JSONArray;import net.sf.json.JSONObject;import sram.thread.ChatRoomClientReaderThread;import sram.user.Message;import sram.user.User;public class LoginFrame {private JFrame frame;private JLabel usernameLabel;private JLabel nicknameLabel;private JTextField usernameText;private JTextField nicknameText;private JButton btnRest;private JButton btnLogin;private JPanel p1,p2,p3;public LoginFrame(){init();listener();}public void init(){frame = new JFrame();usernameLabel = new JLabel("用户名");nicknameLabel = new JLabel("昵 称");usernameText = new JTextField(10);nicknameText = new JTextField(10);btnRest = new JButton("重置");btnLogin = new JButton("登录");p1 = new JPanel();p2 = new JPanel();p3 = new JPanel();frame.setLayout(new GridLayout(3, 1));p1.add(usernameLabel);p1.add(usernameText);p2.add(nicknameLabel);p2.add(nicknameText);p3.add(btnRest);p3.add(btnLogin);frame.add(p1);frame.add(p2);frame.add(p3);frame.setResizable(false);frame.pack();Toolkit t = Toolkit.getDefaultToolkit(); //获取工具包Dimension d = t.getScreenSize(); //获取屏幕尺寸frame.setLocation(d.width/2-175,d.height/2-40);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}public void listener(){btnLogin.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String username = usernameText.getText();String nickname = nicknameText.getText();User user = new User(username,nickname);Message msg = new Message();msg.setType(1);msg.setFromUser(user);try {Socket s = new Socket("127.0.0.1",6666);PrintWriter pw = new PrintWriter(s.getOutputStream(),true);pw.println(JSONObject.fromObject(msg).toString());BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));String message = br.readLine();System.out.println("客户端接受的消息是:"+message);Message msgReturn = (Message) JSONObject.toBean(JSONObject.fromObject(message), Message.class);switch (msgReturn.getType()) {case 10:System.out.println("开启聊天窗口");String usersStr = msgReturn.getMessage();List<User> list = JSONArray.toList(JSONArray.fromObject(usersStr),User.class);ClientFrame f = new ClientFrame(user,s,list);new Thread(new ChatRoomClientReaderThread(s, f)).start();frame.setVisible(false);break;case 11:s.close();JOptionPane.showMessageDialog(null, "用户名已经存在,请重新输入后登录");break;default:break;}} catch (UnknownHostException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}});}public static void main(String[] args) {new LoginFrame();}}

1234567891011121314151617181922232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811911122123124125126

ChatRoomClientReaderThread

package sram.thread;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import .Socket;import java.text.SimpleDateFormat;import java.util.Date;import net.sf.json.JSONObject;import sram.frame.ClientFrame;import sram.user.Message;import sram.user.User;import sram.util.FriendsTreeFlushUtil;public class ChatRoomClientReaderThread implements Runnable {private Socket socket;private BufferedReader br ;private PrintWriter pw;private ClientFrame frame;public ChatRoomClientReaderThread(Socket socket,ClientFrame frame) throws IOException {this.socket = socket;this.frame = frame;br = new BufferedReader(new InputStreamReader(socket.getInputStream()));pw = new PrintWriter(socket.getOutputStream(),true);}@Overridepublic void run() {String str = null;try {while((str = br.readLine())!=null){Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("客户端接收的消息是:"+str);Message msg = (Message) JSONObject.toBean(JSONObject.fromObject(str), Message.class);switch (msg.getType()) {case 4: //系统登录消息。User userLogin = msg.getFromUser();if(userLogin.equals(frame.getUser())){frame.getArea().append("[系统消息]:您成功上线了!\r\n");}else{frame.getArea().append("[系统消息]:您的好友"+userLogin.getNickname()+"("+userLogin.getUsername()+")上线了!\r\n");//好友列表增加用户FriendsTreeFlushUtil.insert(frame, userLogin);}break;case 5: //系统退出消息User out = msg.getFromUser();frame.getArea().append("[系统消息]:您的好友"+out.getNickname()+"("+out.getUsername()+")下线了!\r\n");//在好友列表中移除退出的用户FriendsTreeFlushUtil.remove(frame, out);break;case 22: //客户端接收的私聊消息User fromUser = msg.getFromUser();String msgStr = msg.getMessage();frame.getArea().append("【私聊】"+fromUser.getNickname()+"("+fromUser.getUsername()+") "+sdf.format(date)+" 说:");frame.getArea().append(msgStr+"\r\n");break;case 23: //客户端接收的群聊消息User fromU = msg.getFromUser();String msgS = msg.getMessage();if(!frame.getUser().equals(fromU)){frame.getArea().append("【群聊】"+fromU.getNickname()+"("+fromU.getUsername()+") "+sdf.format(date)+" 说:");frame.getArea().append(msgS+"\r\n");}break;}}} catch (IOException e) {e.printStackTrace();}}}

1234567891011121314151617181922232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485

Message

package sram.user;//用来描述发送消息的类。 1登陆(10 成功 11 不成功) 2 (服务器(20 私聊 21 群聊)客户端( 22 私聊,23群聊 )聊天 3退出 4系统登录消息 5 系统退出消息等public class Message {private String message; //发送消息内容private int type; //发送消息类型private User fromUser; //来源自谁的消息private User toUser; //发送给谁public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public int getType() {return type;}public void setType(int type) {this.type = type;}public User getFromUser() {return fromUser;}public void setFromUser(User fromUser) {this.fromUser = fromUser;}public User getToUser() {return toUser;}public void setToUser(User toUser) {this.toUser = toUser;}}

1234567891011121314151617181922232425262728293031323334

User

package sram.user;//用户实体类。登陆成功后,可以被保存在服务器端。public class User {private String username; //用户名,唯一的标识private String nickname;//用户自定义的网络名称public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname;}public User(String username, String nickname) {this.username = username;this.nickname = nickname;}public User() {}@Overridepublic boolean equals(Object obj) {User user = (User)obj;return this.username.equals(user.username);}@Overridepublic String toString() {return nickname+"("+username+")";}}

123456789101112131415161718192223242526272829303132333435

FriendsTreeFlushUtil

package sram.util;import java.util.Enumeration;import javax.swing.tree.DefaultMutableTreeNode;import javax.swing.tree.DefaultTreeModel;import sram.frame.ClientFrame;import sram.user.User;public class FriendsTreeFlushUtil {public static void insert(ClientFrame frame,User u){DefaultMutableTreeNode root = frame.getRoot();DefaultTreeModel model = frame.getModel();model.insertNodeInto(new DefaultMutableTreeNode(u), root, root.getChildCount());}public static void remove(ClientFrame frame,User u){DefaultMutableTreeNode root = frame.getRoot();DefaultTreeModel model = frame.getModel();//获取所有的子节点Enumeration<DefaultMutableTreeNode> children = root.children();while(children.hasMoreElements()){DefaultMutableTreeNode node = children.nextElement();User user = (User) node.getUserObject();if(user.equals(u)){model.removeNodeFromParent(node);}}}}

如果觉得《socket聊天室实现-群聊 私聊 好友列表 完整版》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。