100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > java多线程聊天室(有图形界面)

java多线程聊天室(有图形界面)

时间:2021-07-12 08:13:26

相关推荐

java多线程聊天室(有图形界面)

聊天室分客户端和服务端,可实现的功能:

多人聊天、退出聊天室、发送系统消息

直接上代码吧。

(我用的是idea)

服务端:

package chat;import javax.swing.*;import javax.swing.JTextField;import javax.swing.event.ListSelectionEvent;import javax.swing.event.ListSelectionListener;import java.awt.*;import java.awt.event.*;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.PrintStream;import .ServerSocket;import .Socket;import java.util.ArrayList;class server extends JFrame implements Runnable, ListSelectionListener, ActionListener {private ServerSocket ss;//建立socketprivate ArrayList<ChatThread> users = new ArrayList<>(); //容量能够动态增长的数组DefaultListModel<String> dl = new DefaultListModel<>();private JList<String> userList = new JList<>(dl);//显示对象列表并且允许用户选择一个或多个项的组件。单独的模型 ListModel 维护列表的内容。//消息输入栏JTextField jtf = new JTextField();public server() throws Exception{this.setTitle("服务器端");//窗口名称this.add(userList, "North");JPanel jpl = new JPanel();this.add(jpl, "South");//将消息输入栏设为一栏jtf.setColumns(1);jpl.setLayout(new BorderLayout());jpl.add(jtf, BorderLayout.NORTH);JButton jbt1 = new JButton("发送消息");jpl.add(jbt1, BorderLayout.WEST);//发送消息//发送消息jbt1.addActionListener(this);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setLocation(400,100);this.setSize(500, 400);this.setVisible(true);this.setAlwaysOnTop(true);ss = new ServerSocket(80);//绑定80端口new Thread(this).start();//监听用户端的加入}@Overridepublic void run() {while(true){try{Socket s = ss.accept();//等待客户端连接ChatThread ct = new ChatThread(s); //为该客户开一个线程users.add(ct); //将每个线程加入到usersct.start();}catch (Exception ex){ex.printStackTrace();javax.swing.JOptionPane.showMessageDialog(this,"服务器异常!");System.exit(0);}}}//发送消息按钮点击事件监听@Overridepublic void actionPerformed(ActionEvent e) {String label = e.getActionCommand();if(label.equals("发送消息")){handleAll();}}public void handleAll(){if(!jtf.getText().equals("")){sendMessage("ALL#" + jtf.getText());//发送完后,输入框中内容为空jtf.setText("");}}//发送消息public class ChatThread extends Thread{Socket s;private BufferedReader br;private PrintStream ps;public boolean canRun = true;String nickName = null;public ChatThread(Socket s) throws Exception{this.s = s;br = new BufferedReader(new InputStreamReader(s.getInputStream()));//读取服客户端数据ps = new PrintStream(s.getOutputStream());//向客户端发送数据}public void run(){while(canRun){try{String msg = br.readLine();//接收客户端发来的消息String[] strs = msg.split("#");switch (strs[0]) {case "LOGIN" -> {//收到来自客户端的登录消息nickName = strs[1];dl.addElement(nickName);userList.repaint();sendMessage(msg);}case "MSG", "FSMSG" -> sendMessage(msg);case "OFFLINE" -> {//收到来自客户端的退出消息sendMessage(msg);dl.removeElement(strs[1]);// 更新当前在聊天室内的用户List列表userList.repaint();}}}catch (Exception ignored){System.out.println("出现异常");}}}}public void sendMessage(String msg){//服务器端发送给所有用户for(ChatThread ct : users){ct.ps.println(msg);}}@Overridepublic void valueChanged(ListSelectionEvent e) {// TODO 自动生成的方法存根}public static void main(String[] args) throws Exception{new server();}}

客户端:

package chat;import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.PrintStream;import .Socket;public class client1 extends JFrame implements Runnable,ActionListener {//northprivate JMenuBar bar = new JMenuBar();private JMenu menu = new JMenu("关于");private JMenuItem about = new JMenuItem("聊天室信息");private JMenuItem exit = new JMenuItem("退出聊天室");JPanel north = new JPanel();DefaultListModel<String> dl = new DefaultListModel<String>();//用来修改JListprivate JList<String> userList = new JList<String>(dl);//用来展示和选择//center面板JPanel center = new JPanel();JTextArea jta = new JTextArea(10,20);JScrollPane js = new JScrollPane(jta);JPanel operPane = new JPanel();//发送消息的操作面板JLabel input = new JLabel("请输入:");JTextField jtf = new JTextField(24);private JButton jbt = new JButton("发送消息");private BufferedReader br = null;private PrintStream ps = null;private String nickName = null;public client1() throws Exception{//north 菜单栏bar.add(menu);menu.add(about);menu.add(exit);about.addActionListener(this);exit.addActionListener(this);BorderLayout bl = new BorderLayout();north.setLayout(bl);north.add(bar,BorderLayout.NORTH);add(north,BorderLayout.NORTH);//center 聊天消息框 发送消息操作面板jta.setEditable(false);//消息显示框是不能编辑的BorderLayout bl3 = new BorderLayout();center.setLayout(bl3);FlowLayout fl = new FlowLayout(FlowLayout.LEFT);operPane.setLayout(fl);operPane.add(input);operPane.add(jtf);operPane.add(jbt);center.add(js,BorderLayout.CENTER);//js消息展示框JScrollPanecenter.add(operPane,BorderLayout.SOUTH);add(center,BorderLayout.CENTER);js.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);//需要时才显示滚动条//鼠标事件,点击jbt.addActionListener(this);this.setDefaultCloseOperation(EXIT_ON_CLOSE);nickName = JOptionPane.showInputDialog("用户名:");this.setTitle("聊天室-"+nickName);this.setSize(500,400);this.setVisible(true);Socket s = new Socket("10.100.35.39", 80);//连接到指定主机(即本机)的指定端口号80br = new BufferedReader(new InputStreamReader(s.getInputStream()));//读取服务器端数据ps = new PrintStream(s.getOutputStream());//向服务器端发送数据new Thread(this).start();ps.println("LOGIN#" + nickName);//发送登录信息,消息格式:LOGIN#nickNamejtf.setFocusable(true);//设置焦点//键盘事件,实现当输完要发送的内容后,直接按回车键,实现发送//监听键盘相应的控件必须是获得焦点的情况下才能起作用jtf.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {if(e.getKeyCode() == KeyEvent.VK_ENTER) {ps.println("MSG#" + nickName + "#" + jtf.getText());//发送消息的格式:MSG#nickName#message//发送完后,是输入框中内容为空jtf.setText("");}}});//监听系统关闭事件,退出时给服务器端发出指定消息this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {ps.println("OFFLINE#" + nickName);//发送下线信息,消息格式:OFFLINE#nickName}});}public void run(){//客户端与服务器端发消息的线程while (true){try{String msg = br.readLine();//读取服务器是否发送了消息给该客户端String[] strs = msg.split("#");//判断是否为服务器发来的登陆信息if(strs[0].equals("LOGIN")){if(!strs[1].equals(nickName)){//不是本人的上线消息就显示,本人的不显示jta.append(strs[1] + "加入聊天室\n");dl.addElement(strs[1]);//DefaultListModel来更改JList的内容userList.repaint();}}else if(strs[0].equals("MSG")){//接到服务器发送消息的信息if(!strs[1].equals(nickName)){//别人发送的消息jta.append(strs[1] + ":" + strs[2] + "\n");}else{jta.append("我:" + strs[2] + "\n");}}else if(strs[0].equals("ALL")){jta.append("系统消息:" + strs[1] + "\n");}}catch (Exception ex){//如果服务器端出现问题,则客户端强制下线JOptionPane.showMessageDialog(this, "聊天室已关闭。");System.exit(0);}}}@Overridepublic void actionPerformed(ActionEvent e) {//鼠标点击事件String label = e.getActionCommand();if(label.equals("发送消息")){handleSend();}else if(label.equals("聊天室信息")){JOptionPane.showMessageDialog(this, "该聊天室由xxx制作\n感谢使用");//这里可以改成别的话,随你心意}else if(label.equals("退出聊天室")){JOptionPane.showMessageDialog(this, "您已成功退出!");ps.println("OFFLINE#" + nickName);System.exit(0);} else{System.out.println("不识别的事件");}}public void handleSend(){//群发消息//发送信息时标识一下来源ps.println("MSG#" + nickName + "#" + jtf.getText());//发送完后,是输入框中内容为空jtf.setText("");}public static void main(String[] args)throws Exception{new client1();}}

不是原创,源代码来自这里,删掉了很多,改了一点点。感谢这位博主的分享。

要实现多人聊天就多复制几个客户端(记得改名)再一起运行就好了。

如果要分别在两台机子上运行,实行不同机器之间的多人聊天,就把电脑的防火墙关掉,然后代码里的主机号改为服务器端所在的电脑的主机号,再ping一下看看是否连接成功就行了。

两台电脑连接成功之后非服务器端所在电脑只需要运行客户端程序,同时服务器端可以同时运行服务器端和客户端,这个问题不大。

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