java实验四 综合应用实验
学院 |
计算机科学与教育软件学院 |
年级、专业、班 |
网络16* |
姓名 |
卟咚君 |
学号 |
1606100*** |
|
实验课程名称 |
Java语言实验 |
成绩 |
||||||
实验项目名称 |
综合应用实验 |
指导老师 |
** |
一.实验目的
熟悉 Java 综合应用程序的开发。
二.实验任务
编写一个 Java 应用程序,实现多人聊天室(需要用到多线程)。
三.实验内容
编写一个 Java 应用程序,实现多人聊天室(需要用到多线程)
client.java
package Socket;
import java.awt.event.ActionListener;
import java.awt.image.ImageObserver;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import javax.swing.*;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
public class client extends JFrame implements ActionListener, Runnable { // 声明client类使用Ruannable接口private static final long serialVersionUID = -8086759001371347347L; //串行版本标识符(不知道为什么要加的,不加class名会有警告)static Socket socket = null; // 定义一个Socket类作为客户端// Scanner input = new Scanner(INput); // 创建一个scanner对象,用作数据输入JTextField field; //多人聊天室文本款Scanner input = new Scanner(System.in); // 创建一个scanner对象,用作数据输入static String name = null; // 定义登录客户端的用户名字static String number=null; //定义是哪一个客户端
private static JTextArea textArea; //定义要发送的信息框//String lineSeparator;JButton setButton; //定义一个发送按钮static client logint; //定义一个登录窗口public client() { //客户端构造函数,初始化客户端多人聊天界面super("多人聊天室-欢迎您,"+name); //指向JFrame类,定义窗口名字textArea = new JTextArea(10, 35); //文本框显示10行30个字符的内容textArea.setEditable(false); //设定这个文本域不可修改JScrollPane jsp = new JScrollPane(textArea); //为文本域加上滚动条jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); //确定垂直滚动条何时显示在滚动窗格上Container con = this.getContentPane(); // 生成一个容器con.setLayout(new FlowLayout()); //流式布局JLabel lbBg1 = new JLabel(" 用户:"+client.name+" "); //在客户端的第一行显示用户名lbBg1.setBounds(0, 0, ImageObserver.WIDTH, ImageObserver.HEIGHT); //设定lbBg1的布局con.add(lbBg1); //加入容器con.add(jsp); //将滚动条(还有文本域)加入容器JLabel L = new JLabel(); //创建一个JLabel组件显示图像L.setIcon(new ImageIcon("E:\\开发工具\\java\\byd001\\photo\\byd001_"+((int)(Math.random() * 100)%5+1)+".jpg")); // 路径下的随机照片添加到L这个组件上来L.setVerticalAlignment(SwingUtilities.CENTER); //L这个组件居中con.add(L); //将组件L加入容器field = new JTextField(20); //创建一个文本框,输入发送的信息setButton = new JButton("发送"); //创建一个按钮,用于触发发送消息事件setButton.addActionListener(this); //添加监控事件JPanel pan2 = new JPanel(); //创建一个面板组件 pan2.add(field); //将文本框加入面板组件pan2.add(setButton); //将发送按钮加入面板组件con.add(pan2); //将面板组件加入容器this.setResizable(false); //设定窗口不能改变大小this.setSize(450, 320); //设定窗口的大小setLocationRelativeTo(null); //设置窗口居中this.setVisible(true); //显示窗口this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置用户在此窗体上发起"close"时关闭程序}public client(int a) { //重载构造函数,创建一个登录窗口super("多人聊天室-登录窗口"); //指向JFrame类,定义窗口名字Container con = this.getContentPane(); //定义一个容器类con.setLayout(new FlowLayout()); //流式布局JLabel lbBg1 = new JLabel(" "); //为了是图片居于中心,在前面设置一段空格lbBg1.setBounds(0, 0, ImageObserver.WIDTH, ImageObserver.HEIGHT); con.add(lbBg1); //将这一段空格加入容器// con.setLayout(new GridLayout(5,1));JLabel L = new JLabel(); //定义一个JLabel组件显示图像L.setIcon(new ImageIcon("E:\\开发工具\\java\\byd001\\photo\\byd001_0.jpg")); // 将登录图像添加到L这个组件上来L.setVerticalAlignment(SwingUtilities.CENTER);con.add(L); //将显示登录图像的控件加入容器JPanel pan1 = new JPanel(); //定义一个面板组件pan1JLabel L1 = new JLabel("用户:"); // 显示文本的JLabel组件JTextField te1 = new JTextField(15); // 用户输入框,括号内是输入框长度pan1.add(L1); //将L1加入面板组件pan1.add(te1); //将用户输入框加入面板组件con.add(pan1); //将面板组件加入容器JPanel pan2 = new JPanel(); //定义一个面板组件pan2JLabel L2 = new JLabel("密码:"); // 显示文本的JLabel组件JPasswordField te2 = new JPasswordField(15);// PasswordField的使用密码输入框te2.setEchoChar('*'); //用*显示输入的数据pan2.add(L2);pan2.add(te2);con.add(pan2);JButton B1 = new JButton(" 登录 "); //登录控件ButtonListener li1 = new ButtonListener(te1, te2); //按钮触发事件B1.addActionListener(li1); // 给登录按钮添加监听con.add(B1);JButton B2 = new JButton(" 取消 ");con.add(B2);this.setSize(300, 220); //设置窗体大小setLocationRelativeTo(null); //设置窗口居中this.setResizable(false); //窗体大小设置为不可改this.setVisible(true); //窗体设置为可见}public void actionPerformed(ActionEvent event) { //设置发送按钮的监听Object source = event.getSource(); if ((source == setButton)) {// 如果确定按钮被按下,则将文本框的文本添加到父窗体的文本域中textArea.append("(你)");try {Thread.sleep(1000); // 线程休眠1秒钟PrintWriter out = new PrintWriter(socket.getOutputStream());// 使用PrintWriter建立一个向socket发送信息的通道String msg = field.getText();out.println(name + "说:" + msg);out.flush(); // 清空缓冲区out中的数据} catch (Exception e) {System.out.println("服务器已断开连接");}}}public static void main(String[] args) {logint = new client(1); //使用创建登录界面的构造函数}public void run() { // 重写Runnable接口的run()方法try {Thread.sleep(1000); // 线程休眠1秒钟BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));// getInputStream()用来获取socket传来的字节流,用InputStreamReader将字节流转换成字符流,然后缓存到BufferedReader缓冲区in中while (true) {// System.out.println(in.readLine()); // 将缓冲区中的字符流逐行输出,没有内容则进入阻塞状态String str = in.readLine();textArea.append(str + "\n");// System.out.println("abc");}} catch (Exception e) {// e.printStackTrace();// System.out.println("服务器已断开连接");textArea.append("服务器已断开连接" + "\n");}}public class ButtonListener implements java.awt.event.ActionListener { //登录,取消按钮监听public JTextField te1 = new JTextField(); // 传参public JPasswordField te2 = new JPasswordField();public ButtonListener(JTextField te1, JPasswordField te2) {//重载窗体上的用户框,密码框传到监听上来this.te1 = te1;this.te2 = te2;}public void actionPerformed(ActionEvent e) { // 捕获点击动作String zhang = te1.getText(); // getText 用于获取输入框内的东西String mi = String.valueOf(te2.getPassword()); // 获得密码框内的东西(获取的不同方法读者可以自行百度)if (mi.equals("12345")) { // 设置账号密码匹配(一直连不上数据库,只能设置一个非常简单的登录密码来模拟一下程序)int x = (int) (Math.random() * 100); // 随机生成一个数值作为客户端的序号name=zhang; //用户名logint.setVisible(false); //将登录界面设置为不可见,假设关闭了登录界面client t = new client(); // 创建一个客户端client.number = "client" + x; // 客户端的名字就是“client”加上随机序号textArea.append("************客户端" + x + "*************" + "\n");try {socket = new Socket("127.0.0.1", 2333); // 连接服务器,网址是本机地址,端口是2333textArea.append("已经连上服务器了" + "\n");} catch (Exception e1) {textArea.append("连接服务器失败" + "\n");}Thread print = new Thread(t); // 创建一个print线程print.start(); // 调用start(),将print线程从新建状态转换成就绪队列状态} else {JOptionPane.showConfirmDialog(null, "用户名或密码错误!","提示",JOptionPane.DEFAULT_OPTION);//弹出提示窗口提示用户名或者密码错误}}}
}
server.java
package Socket;
import java.io.BufferedReader;
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.List;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class server extends JFrame implements Runnable { // 声明server类使用Ruannable接口private static final long serialVersionUID = 2162755171253451698L; //串行版本标识符(不知道为什么要加的,不加class名会有警告)static List<Socket> socketList = new ArrayList<Socket>(); // 动态Socket类数组static Socket socket = null; // 定义一个Socket,建立负责连接到服务器的套接字对象static ServerSocket serverSocket = null; // 定义一个ServerSocket对象,负责将客户端和服务器端连接起来private static JTextArea textArea;
public server() { // server类的构造函数super("服务端示例");try {serverSocket = new ServerSocket(2333); // 创建一个ServerSocket对象,端口号为9999} catch (IOException e) {e.printStackTrace(); // 出现异常则打印出异常的位置}textArea = new JTextArea(10, 30); //设置文本域textArea.setEditable(false); //文本域不能更改JScrollPane jsp = new JScrollPane(textArea); //为文本域加上滚动条jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); //确定垂直滚动条何时显示在滚动窗格上getContentPane().add("Center", new JScrollPane(jsp)); //将文本域加入容器的中间this.pack(); //窗口自适应大小this.setVisible(true); //窗体设置为可见this.setResizable(false); //窗体大小设置为不可改setLocationRelativeTo(null); //设置窗口居中this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置用户在此窗体上发起"close"时关闭程序}public static void main(String[] args) {server t = new server(); // 创建一个server对象textArea.append("************服务端*************" + "\n");int count = 0; // 计数器count,记录登录到该服务器的客户端个数while (true) {try {socket = serverSocket.accept(); // 返回一个和客户端Socket对象相连接的Socket对象socketcount++; // 计算器count加一// System.out.println("第" + count + "个客户已连接");textArea.append("第" + count + "个客户已连接" + '\n');socketList.add(socket); // 将这个socket加入动态Socket类数组中} catch (IOException e) {e.printStackTrace();}Print p = new Print(socket); // 创建一个Print类,用于存储和输出目前所有的聊天内容Thread read = new Thread(t); // 创建一个线程readThread print = new Thread(p); // 创建一个线程printread.start(); // 调用start(),将read线程从新建状态转换成就绪队列状态print.start(); // 调用start(),将print线程从新建状态转换成就绪队列状态}}public void run() { // 重写Runnable接口的run()方法try {Thread.sleep(1000); // 线程休眠1秒钟BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));// getInputStream()用来获取服务端传来的字节流,用InputStreamReader将字节流转换成字符流,然后缓存到BufferedReader缓冲区in中while (true) {String jieshou = in.readLine(); // 从缓冲区中读取一行// System.out.println(jieshou);textArea.append(jieshou + "\n");for (int i = 0; i < socketList.size(); i++) {Socket socket = socketList.get(i); // 依次取出和客户端相连接的Socket对象PrintWriter out = new PrintWriter(socket.getOutputStream()); // 使用PrintWriter建立一个向socket发送信息的通道if (socket != server.socket) {out.println(jieshou); // 如果不是当前客户端,则直接显示消息} else {out.println(jieshou); // 如果是当前客户端,则显示是自己发送的消息}out.flush(); // 清空缓冲区out中的数据}}} catch (Exception e) {textArea.append("客户已断开连接" + "\n");}}
}class Print implements Runnable { // 声明Print类使用Ruannable接口,Print类用于存储和输出目前所有的聊天内容static List<Socket> socketList = new ArrayList<Socket>(); // 动态Socket类数组Scanner input = new Scanner(System.in); // 创建一个scanner对象,用作数据输入public Print(Socket s) { // 构造函数try {socketList.add(s); // 将Socket对象加入Socket类数组中} catch (Exception e) {// e.printStackTrace();System.out.println("客户已断开连接");// textArea.append("客户已断开连接"+"\n");}}public void run() { // 重写Runnable接口的run()方法try {Thread.sleep(1000); // 线程休眠1秒钟while (true) {String msg = input.next(); // 获取输入的字符for (int i = 0; i < socketList.size(); i++) {Socket socket = socketList.get(i);PrintWriter out = new PrintWriter(socket.getOutputStream()); // 使用PrintWriter建立一个向socket发送信息的通道out.println("服务端说:" + msg);out.flush(); // 清空缓冲区out中的数据}}} catch (Exception e) {System.out.println("客户已断开连接");}}
}
四.实验结果记录(程序运行结果截图)
1.先开启服务端
2.开启一个客户端,进行用户登录,进入聊天界面
3.登录密码出错时,提示错误
4.多个用户登录
5.多个用户进行聊天
6.退出客户端
五.实验心得与总结
通过这次实验,掌握开发 Java 应用程序的步骤,熟悉类的基本设计方法,根据 Java 类的继承机制有效解决问题。对Java 的多线程应用程序开发方法有了更深入的了解,熟悉了 Java 系统图形用户界面的工作原理和界面设计步骤,掌握图形用户界面的各种常用组件的使用方法和图形用户界面各种布局策略的设计与使用。原本这个实验可以通过简单的多线程在命令行上可以实现的,但是,我想把之前学过的类的继承以及图像用户界面和多线程结合起来,实现一个多人在线的聊天室的一个可视化程序。由于对java语言运用的不熟练,导致实验花了比较多的时间。在多人聊天室中,每一个打开客户端的程序都会分配一个客户端号,并且和服务端进行相连。在服务器中,运用ServerSocket对象,将客户端和服务器端连接起来,每有一个客户端优用户登录,就用serverSocket.accept()创建一个server与客户端进行连接,借鉴了网上一些getInputStream()用来获取服务端传来的字节流的方法,实现客户端和服务器之间的通信连接,也是通过服务器将一个客户端的消息发送给同一个聊天室的其他客户端上的用户。一开始客户端上的用户是以客户端号进行鉴别的,但这不太符合我们的日常情况。所以我添加了一个用户登录的界面,记录用户的信息,这样聊天的时候就可以直接显示用户的名字了。在登录界面跳转到聊天界面的时候,我曾设计了一个login类,专门用于用户登录的,但是发现在登录成功后,如何触发打开聊天界面和关闭登录界面不是很懂的实现,所以后来我将登录界面写入cilent类的一个重载的构造函数中,如果登录成功的话,我就将用户登录的界面进行屏蔽,假装关闭了,然后新建一个窗口,也就是聊天界面,这样就能实现登录界面到聊天界面的转换。为了美观,我给登录的时候添加了一个登录头像,在聊天的时候,随机给用户添加了一个新的聊天头像,这样看起来好看一点。遇到的问题是,我在登录界面的时候,尝试用eclipse连接oracle数据库,试了一个下午都不成功,试了网上的方法也都以失败告终,后来不得不使用了一些简单的登录验证方式来暂时替代一下。通过这次的实验,提高了自己的编程能力,对java语言有了更深入的了解。
java实验四 综合应用实验相关推荐
- linux 程序实验总结,Linux实验报告(实验四) shell编程实验
实验四 shell编程实验(二) 班级:姓名:学号:上机时间:年月日 任课教师:实验教师:实验成绩: 一.实验目的 综合Linux常用命令和vi编辑器的使用,熟练掌握shell脚本编程. 二.实验注意 ...
- 多思计组实验实验四、数据通路实验
实验四.数据通路实验 一.实验目的: 1.理解总线的概念和作用. 2.连接运算器与存储器,理解计算机的数据通路. 3.理解微命令与微操作的概念. 二.预习要求: 1.读懂实验电路图. 2.在实验之前填 ...
- 微控制器实验计算机组成原理,组成原理实验四 微控制器实验
实验四 微控制器实验 实验四微控制器实验 实验四 一.实验目的 1.掌握时序产生器的组成原理. 微控制器实验 2.掌握微程序控制器的组成原理. 3.掌握微程序的编制.写入,观察微程序的运行.二.实验设 ...
- 计算机组成原理学习-实验四 模型机实验(简易版)(详细、人话)
如果你对其他计算机组成原理知识感兴趣,请考虑阅读我的专栏: 计算机组成原理[专栏] 须知 本文仅作学习笔记使用,仅在CSDN网站发布,如果在其他网站发现,均为侵权行为,请举报.作者:小王在努力. 实验 ...
- 计算机网络实验四 VLAN配置实验
实验四 VLAN配置实验 一.实验目的: 了解华为交换机的基本功能. 掌握虚拟局域网VLAN的相关知识,配置交换机VLAN功能. 掌握VLAN的创建.Access和Trunk接口的配置方法. 掌握用于 ...
- 计算机网络综合组网实验、综合组网实验
软件学院综合性.设计性实验报告 专业:Java 年级/班级:2019级Java(2)班 2020-2021 学年第 二 学期 课程名称 计算机网络 指导教师 李晓艳 学号 姓名 1928424 ...
- 软件工程汇编程序设计——分支程序实验,循环程序实验,综合程序设计实验
实验2-分支程序实验 1.已知X.Y.Z.MAX为16位的带符号数,求三个数中最大值,结果存入MAX单元. 输入变量的初值定义:输出结果的保存说明: stack segment stackdb 50 ...
- mysql安全实验测验答案_实验四∶数据库安全性实验报告.doc
资源描述 1 / 2实验四:数据库安全性班级:软件工程 0918 姓名:许啸 学号:0911610819[实验目的] :验证数据库安全性[实验要求] :1)新建一个登陆名为 tom,密码为 tom00 ...
- 计算机组成原理实验四 微程序控制器实验报告
我班算是几乎最后一个做实验的班级了,报告参考了一些朋友提供的数据加上一些自己的主观拙见,本人水平有限加之制作仓促难免有错误,望大家批评指正. 4.1 微程序控制器实验 一.实验目的 (1) 掌握微程序 ...
最新文章
- 移动应用开发的六大编程语言
- 传统图像处理与深度学习又一结合:时空多尺度非局部自相似集成视频超分
- 基于OpenCV的图像强度操作
- html随机数游戏,js实现随机数小游戏
- Django创建项目
- STL源码剖析 set相关算法
- java ajax 联动菜单_java结合jQuery.ajax实现左右菜单联动刷新列表内容
- PostgreSQL update tbl1 from tbl2 一对多的注意事项(到底匹配哪条)
- 光棍节就要到了,要不要给你介绍个 Python 对象?| CSDN 博文精选
- Unity使用Newtonsoft报错的解决方案
- CentOS 7 Tomcat 安装
- ESXi6.7修改静态ip地址
- 网站流量分析指标-PV/UV/PR/ip分析及区别
- 利用FPGA制作数字电压表
- Tomcat部署静态页面
- 外存及虚拟存储器管理
- 比最快的超级计算机快一百万亿倍!中国科学家实现“量子计算优越性”里程碑
- 无法在Android手机上拨打或接听电话,如何解决
- nodeJS的环境搭建以及nodeJS和npm简介
- ANSYS Workbench接触设置—对称和非对称接触