编写一个 Java 应用程序,实现图形界面多人聊天室(多线程实现),要求聊天室窗口标题是 “欢迎使用 XXX 聊天室应用”,其中 XXX 是自己的班级姓名学号,如“软件 171 张三 1234”。

客户端

import java.awt.BorderLayout;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import java.io.*;
class Login extends JFrame implements ActionListener{
    //用户名
    JPanel jp1=new JPanel();
    JLabel jl1=new JLabel("用户名");
    public JTextField jtf1=new JTextField(15);
    //密码
    JPanel jp2=new JPanel();
    JLabel jl2=new JLabel("密码");
    JPasswordField jpf2 = new JPasswordField(15);
    //登入取消按钮
    JPanel jp3=new JPanel();
    JButton jbt1=new JButton("登入");
    JButton jbt2=new JButton("取消");
    
    public Login() {
        // TODO 自动生成的构造函数存根
        this.setTitle("客服端登入窗口");
        Container con =this.getContentPane();
        con.setLayout(new FlowLayout());
        //用户名
        jp1.add(jl1);
        jp1.add(jtf1);
        jtf1.addActionListener(this);
        //密码
        jpf2.setEchoChar('*');  //用*显示密码框输入的数据
        jp2.add(jl2);
        jp2.add(jpf2);
        jpf2.addActionListener(this);
        //登入取消按钮
        jp3.add(jbt1);
        jp3.add(jbt2);
        //添加到当前窗口容器
        con.add(jp1);
        con.add(jp2);
        con.add(jp3);
        this.setSize(500, 300);    //设置窗体大小
        setLocationRelativeTo(null); //设置窗口居中
        this.setResizable(false);  //窗体大小设置为不可改
        this.setVisible(true);  //窗体设置为可见
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        //光标聚焦在用户框中
        jtf1.requestFocus(); 
        //为登入按钮添加监听器
        jbt1.addActionListener(new ActionListener() { 
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO 自动生成的方法存根
                String name=jtf1.getText();
                String password=new String(jpf2.getPassword()); //获取密码框中的密码
                try {
                    if(password.equals("123")) {
                        setVisible(false);
                        new Client(jtf1.getText());
                    }
                    else {
                        JOptionPane.showConfirmDialog(null, "用户名或密码错误!",
                                "提示",JOptionPane.DEFAULT_OPTION);
                    }
                } catch (Exception e2) {
                    // TODO: handle exception
                    e2.printStackTrace();
                }
            }
        });
        jbt2.addActionListener(new ActionListener() { //为取消按钮添加监听器
            
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO 自动生成的方法存根
                try {
                    setVisible(false);
                } catch (Exception e2) {
                    // TODO: handle exception
                }
            }
        });
    }
    //移动光标聚集
    public void actionPerformed(ActionEvent e) {
        Object o=e.getSource();
        if(o==jtf1) {
            jpf2.requestFocus();
        }
    }
}

public class Client extends JFrame  {
    public DataOutputStream dos=null;
    public DataInputStream dis=null;
    public Socket s=null;
    public ServerSocket sc=null;
    //
    public JTextArea jta=new JTextArea(10,20);
    public JTextField jtf=new JTextField(20);
    public JScrollPane jsp = new JScrollPane(jta);
    static final String CONNSTR="127.0.0.1";
    public String ClientName="";

    //构造函数初始化
    Client(String tClientName) throws IOException{
        ClientName=tClientName;
        this.setTitle("客服端:" ClientName);
        jta.setEditable(false); //文本显示框不可编辑
        this.add(jtf,BorderLayout.SOUTH);
        this.add(jsp,BorderLayout.CENTER);
        //默认的设置是超过文本框才会显示滚动条,以下设置让滚动条一直显示
        jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        //连接服务器
        
        try {
            s=new Socket(CONNSTR,9995);
            new ThreadClient(s,this).start();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            JOptionPane.showConfirmDialog(null, "用户连接服务器失败",
                    "提示",JOptionPane.DEFAULT_OPTION);
        }
        //发送登入信息到服务器
        String firstStr="\"" ClientName "\":" "登入成功";
        DataOutputStream firstdataOutputStream = new DataOutputStream(s.getOutputStream());
        //发送用户名到服务端
        firstdataOutputStream.writeUTF(firstStr);
        firstdataOutputStream.flush();
        //
        this.setBounds(300,300,300,400);        
        //this.setSize(500, 300);    //设置窗体大小
        setLocationRelativeTo(null); //设置窗口居中
        this.setVisible(true);  //窗体设置为可见
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        jtf.requestFocus();
        //
        
        jtf.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO 自动生成的方法存根
                String str=jtf.getText();
                try {
                    if(str.length()>0) {
                        str="\"" ClientName "\":" str;
                        sendMessage(str, s);
                        jtf.setText("");
                    }
                } catch (Exception e2) {
                    // TODO: handle exception
                    e2.printStackTrace();
                    str="\"" ClientName "\":" "已退出";
                    sendMessage(str,s);
                }
                
            }
        });
    }
    //客服端发送信息到服务器
    protected void sendMessage(String message, Socket s) {
        try {
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            dos.writeUTF(message);
            dos.flush();    
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        new Login();
    }
}
//定义线程类,读取服务器发送的信息
class ThreadClient extends Thread {
    private Socket s;
    private Client clientChat;

    ThreadClient(Socket socket, Client clientChat) {
        this.s = socket;
        this.clientChat = clientChat;
    }
    @Override
    public void run() {
        String message;
        try {
            while (true) {
                    DataInputStream DataInputStream = new DataInputStream(s.getInputStream());
                    message = DataInputStream.readUTF();
                    clientChat.jtf.setText("");
                    clientChat.jta.append(message "\n");
                }
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
                e.printStackTrace();
                message="\"" clientChat.ClientName "\":" "已退出";
                clientChat.sendMessage(message,s);
        }
    }
}

服务端

import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

import javax.naming.ldap.LdapName;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Server extends JFrame {
    //static List<Socket>ls=new ArrayList<Socket>();
    //static List<String>lname=new ArrayList<String>();
    public static Map<Socket,String> socketsMaps 
    = Collections.synchronizedMap(new HashMap<Socket,String>());
    //
    ServerSocket sc=null;
    Socket s=null;
    public JTextArea jta=new JTextArea(10,20);
    public JScrollPane jsp=new JScrollPane(jta);
    public String ServerName="服务器";
    static int number=1;
    Server() throws IOException{
        super();
        setTitle("服务器");
        jta.setEditable(false); //文本显示框不可编辑
        this.add(jsp,BorderLayout.CENTER);
          //默认的设置是超过文本框才会显示滚动条,以下设置让滚动条一直显示
        jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        //this.add(jta,BorderLayout.CENTER);  //不需要重复添加
        this.setBounds(300,300,300,400);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //
    }
    public void init() {
        int count = 0; // 记录登录到该服务器的客户端个数
            try {
                sc = new ServerSocket(9995); // 创建一个ServerSocket对象,端口号为1906
                jta.append("服务器已启动" '\n');
                while (true) {
                    Socket socket=sc.accept();
                    new ThreadServer(socket,this).start();
                }
            }
            catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
            
    }
    
    public static void main(String[] args) throws IOException{
        new Server().init();
    }
}

class ThreadServer extends Thread {
    private Socket ts;
    private Server tsr;
    ThreadServer(){};
    ThreadServer(Socket s,Server sr)
    {
        this.ts = s;
        this.tsr=sr;
    }
    public void run() {
        
        try {
            while(true)
            {
                DataInputStream dis = new DataInputStream(ts.getInputStream());
                String message=dis.readUTF();
                if(message.endsWith(":登入成功")) {
                    message.replaceAll(":登入成功", "");
                    tsr.socketsMaps.put(ts,message);
                }
                tsr.jta.append(message '\n');
                Set<Socket> sockets = tsr.socketsMaps.keySet();
                for(Socket tts : sockets) {
                    DataOutputStream dos = new DataOutputStream(tts.getOutputStream());
                    dos.writeUTF(message);
                    dos.flush();
                }
            }
        }
        catch (IOException e2) {
            // TODO: handle exception
            e2.printStackTrace();
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持Devmax。

java实现多人聊天室可视化的更多相关文章

  1. 如何在Xcode 8中启用Visual Memory Debugger?

    我将项目从以前版本的Xcode迁移到Xcode8.我想要的是使用新的可视化内存调试器.它可用于新项目,但在我导入的项目中完全缺少.为什么是这样?

  2. Swift - 继承UIView实现自定义可视化组件附记分牌样例

    在iOS开发中,如果创建一个自定义的组件通常可以通过继承UIView来实现。下面以一个记分牌组件为例,演示了组件的创建和使用,以及枚举、协议等相关知识的学习。效果图如下:组件代码:scoreView.swift123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051importUIKitenumscoreType{caseCommon//普通分数面板Best//最高分面板}pr

  3. 使用自动布局可视化格式与Swift?

    我一直在试图使用AutolayoutVisualFormatLanguageinSwift,使用NSLayoutConstraint.constraintsWithVisualFormat。这里有一些例子,没有什么有用的代码,但就我可以告诉应该让类型检查器快乐:但是,这会触发编译器错误:“Cannotconverttheexpression’stype‘[AnyObject]!’totype‘St

  4. Instruments Swift教程:开始

    准备进入Instruments的精彩世界吧!你会发现Instruments可以让调试问题变得轻松的多!在指定的时间间隔上,Instruments会停止app执行并抽取每个线程上的栈帧记录。此外,Xcode9beta中使用模拟器进行Instrument也会导致一些问题。这会打开一个新的Instruments文档。但是,首先你应该看一下Instruments的当前报告。在当前TimeProfiler当中,只有一次instrument,因此只有一条轨迹。它显示了这次instrument的主要内容。

  5. Android – 如何创建家谱图(可视化)

    有大量的家庭树应用程序,但由于某种原因,我找不到如何为Android应用程序创建一个的示例.我是否使用画布,是否有图表库?

  6. android – GpsSatellite.getSnr() – 值范围是多少?

    我正在构建一个Sat-View,为可用的卫星及其信号强度绘制一个小条形图.javadoc没有说明SNR的预期值范围.NMEA-Standard表示0-99,但即使在最佳条件下,我的G1也没有达到该值.我还读到不同的制造商对SNR使用不同的值范围,对于Android设备也是如此吗?或者该平台上是否有统一的价值范围,如果是,它是什么?文档中缺少信息让我怀疑我只是从驱动程序中获得了“原始”SNR,在这种情况下我想知道:您认为什么是可视化未知值范围的最佳方法条形图?解决方法你找到了答案吗?

  7. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  8. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  9. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  10. Python可视化神器pyecharts之绘制地理图表练习

    这篇文章主要介绍了Python可视化神器pyecharts之绘制地理图表,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部