Java实战项目(一)---编写聊天室程序

2023-11-15

刚开始学java,参考《java从入门到精通》这本书,学到网络程序设计基础这一章节,尤其与其他计算机进行通信,觉得还挺有意思的。所有深入地试试做一个小程序—聊天室程序,在代码中加入我自己的理解和困惑,希望能和大家一起探讨,每行的代码基本都有注释,方便大家理解。
编译环境:eclipse(代码可以直接运行)
以下设计到的关于java的主要知识:Swing、多线程、I/O输入输出、TCP

TCP原理基础

TCP网络程序设计是指利用Socket类编写通信程序。利用TCP协议进行通信的两个应用程序是有主次之分的,一个称为服务器程序,另一个成为客户端程序,两者的功能和编写方法大不一样。
服务器端和客户端的交互过程如下图1所示:

服务器端和客户端的交互过程

  1. 服务器程序创建一个ServerSocket(服务器套接字),调用accept()方法等待客户机连接。
  2. 客户端程序创建一个Socket,请求与服务器建立连接。
  3. 服务器接受客户机的连接请求,同时创建一个新的Socket与客户建立联系。随后服务器继续等待新的请求。

流程图

服务器段程序

//服务器端程序
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.List;

import javax.swing.*;

public class TCPServer extends JFrame {
	
	private static final long serialVersionUID = 1L;
	private ServerSocket ss = null;    // 创建服务器套接字接口
	private boolean bStart = false;    // 添加用户标志
	
	private JTextArea taContent = new JTextArea();  // 文本域
	
	private int index = 0;     // 用户个数
	
	List<Client> clients = new ArrayList<Client>();   // 泛型--创建List集合(ArrayList是List的子类)--存储客户数
	
	// 窗口布局                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
	public void launchFrame() {
//		Container con = this.getContentPane();
		taContent.setEditable(false);    // 不可编辑
		
		taContent.setBackground(Color.DARK_GRAY);	// 背景颜色
		taContent.setForeground(Color.YELLOW);		// 文字颜色
		this.add(taContent);		 // 容器中添加文本域
		this.setSize(300, 350);		 // 设置大小
		this.setLocation(400, 200);	
		this.setTitle("TCP Server");
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		tcpMonitor();
	}
	
	// TCP监听
	public void tcpMonitor() {
		try {
			ss = new ServerSocket(8888);   // 服务器套接字8888
			bStart = true;    
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
		try {
			while (bStart) {
				index++;		// index代表人数
				Socket s = ss.accept();    // 等待客户端连接
				Client c = new Client(s);  // 实例化对象--用户
				clients.add(c);
				
				// getInetAddress()--返回此服务器套接字的本地地址
				// getHostAddress()--获取IP地址
				// taContent---文本域
				taContent.append(s.getInetAddress().getHostAddress()   // 文本域添加字--127.0.0.1 connect 1 clients
						+ " connected " + index + " clients\n");
				// public Thread(String threadName)-----创建一个名称为threadName的线程对象
				new Thread(c).start();			// 启动多线程
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				ss.close();     // 关闭套接字
			} catch (IOException e) {
				
				e.printStackTrace();
			}
		}
		
	}
	
	public static void main(String args[]) {
		TCPServer ts = new TCPServer();    // 实例化TCP网络程序
		ts.launchFrame();     // 实现窗口布局、网络连接
	}
	
	private class Client implements Runnable {
		DataInputStream dis = null;    // 数据输入流
		DataOutputStream dos = null;   // 数据输出流
		
		Socket s = null;     // 服务器接受客户端的连接请求,同时创建一个新的套接字与客户端建立连接
		boolean bStart = false;  // 添加用户标志
		
		Client(Socket s) {
			this.s = s;
			try {
				dis = new DataInputStream(s.getInputStream());   // 获取输入数据
				dos = new DataOutputStream(s.getOutputStream());	// 获取输出数据
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			bStart = true;
		}
		
		// 发送数据
		public void sendToEveryClient(String str) {
			try {
				dos.writeUTF(str);	// 输出数据----writeUTF()写出一个UTF-8编码的字符串前面会加上2个字节的长度标识
				dos.flush();    // 刷新
				
			} catch (IOException e) {
				index--;       // 用户数减少
				clients.remove(this);      // 从数组中去除该用户
				taContent.append(s.getInetAddress().getHostAddress()  // Socket s = null
						+ " exited " + index + " clients\n");
				System.out.println("对方退出了!我从List里面去掉了!");
			}
		}
		
		public void run() {
			try {
				while (bStart) {       // 当bStart=true时,读取数据
					String str = dis.readUTF();   // 读取数据
					System.out.println(str);     // 打印信息
					// 发送客户的信息
					for (int i = 0; i < clients.size(); i++) {
						Client c = clients.get(i);   // clients数组中的元素都是Client类的
						c.sendToEveryClient(str);    // 发送信息
					}
				}
			} catch (EOFException e) {
				clients.remove(this);
				taContent.append(s.getInetAddress().getHostAddress()
						+ " exited " + clients.size() + " clients\n");
				System.out.println("client closed");
			} catch (SocketException e) {
				System.out.println("client closed");
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					if (s != null)
						s.close();
					if (dis != null)
						dis.close();
					if (dos != null)
						dos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
}

客户端程序

// 客户端程序
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.*;

public class TCPClient extends JFrame {
	private static final long serialVersionUID = 1L;
	TextArea taContent = new TextArea(); // 文本域
	JTextField tfTxt = new JTextField(20); // 文本框

	JButton send = new JButton("发送"); // 按钮
	JButton connect = new JButton("连接");
	JButton clear = new JButton("清空");

	boolean live = false;
	JPanel p1 = new JPanel();
	JPanel p2 = new JPanel();

	Socket s = null; // 创建客户端套接字
	DataOutputStream dos = null; // 输出流
	DataInputStream dis = null; // 输入流

	boolean bConnected = false; // 连接标志

	Thread t = new Thread(new RecToServer()); // 多线程--new Runnable()接口

	// 窗口布局
	public void launchFrame() {

		taContent.setEditable(false);

		p2.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 5)); // 使用流布局
		p2.add(send); // 3个按钮--send、connect、clear
		p2.add(connect);
		p2.add(clear);

		Container con = this.getContentPane(); // 实例化容器

		con.add(taContent, "North"); // 容器中添加文本域
		con.add(tfTxt, "Center"); // 容器中添加文本框
		con.add(p2, "South"); // 容器中添加面板(面板中是两个按钮)

		this.setSize(300, 350); // this 指代 JFrame
		this.setLocation(400, 200);
		this.setTitle("Chat Client");

		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		// 添加按钮监听
		connect.addActionListener(new Connect()); // 连接按钮
		send.addActionListener(new SendMsg()); // 发送按钮
		clear.addActionListener(new ActionListener() { // 清除按钮监听--使文本框中的内容置空
			public void actionPerformed(ActionEvent e) {
				taContent.setText("");
			}
		});
	}

	// 连接服务器
	public void connectToServer() {
		try {

			s = new Socket("127.0.0.1", 8888); // 客户端创建一个Socket套接字
			dos = new DataOutputStream(s.getOutputStream()); // 数据输出流
			dis = new DataInputStream(s.getInputStream()); // 数据输入流

			bConnected = true; // 连接标识符置为true

		} catch (BindException e) {
			System.out.println("找不到指定的服务器");
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	// 断开链接
	public void disConnect() {
		try {
			if (s != null) {
				s.close(); // Socket s = null
			}

			if (dos != null) {
				dos.close(); // DataOutputStream dos = null
			}
			if (dis != null) {
				dis.close(); // DataInputStream dis = null
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 主程序
	public static void main(String args[]) {
		TCPClient tc = new TCPClient(); // 实例化TCPlient对象
		tc.launchFrame(); // 主程序
	}

	// 连接按钮----监听
	private class Connect implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if (e.getActionCommand() == "连接") { // e.getActionCommand()==获取按钮上的文字(连接)

				connectToServer(); // 连接服务器
				try {
					t.start(); // 启动多线程 Thread t=new Thread(new RecToServer())
				} catch (IllegalThreadStateException ex) {
				}

				connect.setText("断开连接"); // 当连接上服务器以后,连接按钮 变为 断开连接按钮

			} else if (e.getActionCommand() == "断开连接") {
				disConnect(); // 断开连接
				connect.setText("连接");
			}

		}
	}

	// 发送按钮--监听
	private class SendMsg implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if (connect.getActionCommand() == "连接") { // 还没有连接上
				/*
				 * showMessageDialog(Component parentComponent, Object message, String title,int messageType) 
				 * 第一个参数:parentComponent---设置了可以改变窗体的主题信息
				 * 第二个参数:message---显示的消息内容 第三个参数:title---提示框的标题
				 * 第四个参数:messageType---设置了信息提示内容的图标,默认值为INFORMATION_MESSAGE或1
				 */
				JOptionPane.showMessageDialog(TCPClient.this, // 出现提示框
						"没有找到指定的服务器", "错误提示", 1);
			} else { // 连接上了
				String str = tfTxt.getText(); // 获取文本框(发送框)中的内容
				tfTxt.setText("");   // 将文本框(发送框)中的内容置零

				try {
					dos.writeUTF(str);   // 将文本框(发送框)中的内容输出
					dos.flush();        // 不断刷新
				} catch (SocketException ex) {   // 
					System.out.println("没有找到指定的服务器");
					JOptionPane.showMessageDialog(TCPClient.this, "没有找到指定的服务器", "错误提示", 1);
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}

		}
	}

	// 多线程接口
	private class RecToServer implements Runnable {
		public void run() {
			try {
				while (bConnected) {   // 连接标志= true 时
					String str = dis.readUTF();    // 读入数据
					// System.out.println(str);

					taContent.append(str + "\n");   // 在文本域中添加聊天内容str
				}
			} catch (SocketException e) {
				System.out.println("服务器已关闭");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java实战项目(一)---编写聊天室程序 的相关文章

随机推荐

  • python 头条 sign 参数 此篇针对实时列表 请使用73版本的谷歌浏览器

    1 首先谷歌浏览器打开今日头条F12调试找到sources 以旅游模块为例以此类推都一样 网站如https www toutiao com ch news travel 2 ctrl shift f全局搜索 window byted acr
  • MD5算法全解析

    前言 这段时间刚好正在做软件安全的实验和课设 学习了各种加密算法 比如对称加密算法的DES AES 非对称加密算法的RSA 再如今天要讲的主角 单向加密算法的MD5 为什么这么多算法 MD5成为了今天的猪脚呢 这是因为个人感觉在目前Andr
  • 【PTA】最长的括号子串 模拟

    给出一个长度为 n 的 仅包含字符 和 的字符串 计算最长的格式正确的括号子串的长度 例1 对于字符串 来说 最长的格式正确的子串是 长度为 2 例2 对于字符串 来说 最长的格式正确的子串是 长度为 4 字符串长度 0 n 5 10 5
  • 【SSD 代码精读】之 model (Backbone)& loss

    model 1 Backbone 1 ResNet 50 2 截取 ResNet 50 的前半部分作为 backbone 2 Module 3 Loss Function 1 location loss 2 confidence loss
  • Ubuntu下跑Aplaca报错:torch.cuda.0utofMemoryError: CUDA out of memory.解决办法(查看CUDA占用情况&清除GPU缓存)

    缓存不够 并非内存容量不够 错误提示 torch cuda 0utofMemoryError CUDA out of memory Tried to allocate 2 00 MiB PU 0 23 69 GiB total capaci
  • 计算机教育中缺失的一课:命令行环境

    点击蓝字 关注我们 内容来源于 计算机教育中缺失的一课 在 Attribution NonCommercial ShareAlike 4 0 International CC BY NC SA 4 0 下获得许可 另外 还可在蓝桥云课社区
  • linux修改密码提示权限拒绝,linux – ssh命令后权限被拒绝,即使密码正确

    我已经通过网线将Raspberry Pi 2连接到我的笔记本电脑 我正在尝试将文件从计算机传输到raspi但是命令ssh usr blabla local 要求我输入密码 我确信密码是正确的但是我得到了权限否认 请再试一次 我能做什么 我无
  • uni-app App端半屏连续扫码

  • 双向可控硅的工作原理

    先看下图的工作原理 如果想简单一点只要记住一句话即可 只要在G端有信号 那么T1 T2这条路就是通的 只有G在零点的时候才不会导通 主要来看一下应用吧 来看我们公司的一个电路图 其实双向可控硅多数用在交流电路中 简单介绍一下 Q5是三极管
  • 期权开户流程、交易时间和规则详解清晰易懂

    本文将介绍期权开户流程 交易时间和规则详解清晰易懂则 包括期权的定义 期权交易的时间 期权交易的规则和期权交易的风险 本文的结论是 期权交易的时间和规则非常重要 应该遵守交易规则 并且要注意风险 本文来源 期权酱 券商开通期权账户和期权分仓
  • 【ISO14229_UDS_0x23服务详解】

    目录 1 0x23服务 根据地址读取内存服务 2 请求报文格式 2 1 请求报文定义 2 2 请求报文中子函数参数定义 2 3 请求报文中数据参数定义 3 肯定应答报文 3 1 肯定应答报文格式定义 3 2 肯定应答报文数据参数定义 4 支
  • 解决mysql重新安装时输入原密码问题

    1 清除MYSQL的安装目录 默认是C Program Files 2 清除MYSQL数据存放目录 一般在C Documents and Settings All Users windows Application Data目录下 需要注意
  • python练习题

    练习 对于任意数字列表 从键盘输入一个数字 sum表示 找到列表中两两相加等于sum的数字 num list 3 2 4 7 1 sum 5 打印列表 3 2 4 1 fou循环实现 num list 3 2 4 7 1 sum 5 lis
  • ES搜索引擎之ES介绍,安装以及辅助插件Kibana的安装

    文章目录 ES搜索引擎之ES介绍 安装以及辅助插件Kibana的安装 ElasticSearch介绍 1 1为什么会有ElasticSearch搜索引擎 1 2ES的介绍 1 3什么是倒排索引 ElasticSearch的安装 下载elas
  • 强大的4开关升降压BOB电源 可升可降能大能小

    原文来自公众号 工程师 基于电感器的开关架构电源有3中常见的拓扑结构 分别是BUCK降压电源 BOOST升压电源以及BUCK BOOST负压电源 今天介绍的第4中拓扑 4开关BOB电源 在手机 汽车 嵌入式等领域都有广泛应用 它的基本工作原
  • http响应头connection的作用

    http chenchendefeng iteye com blog 461248 有的网站会在服务器运行一段时间后down掉 有很多原因可能造成这种现象 比如tomcat堆和非堆内存设置不足 程序没能释放内存空间造成内存溢出 或者某些进程
  • 渗透测试信息收集

    信息收集 渗透的本质是信息收集 信息收集分为主动信息收集和被动信息收集 主动信息收集能够收集到更多的信息 但是会产生痕迹 容易被溯源 被动信息收集是信息收集的第一步 通过第三方工具进行收集 不与主机直接交互 需要收集的信息包括 域名 子域名
  • TCP\UDP服务器与客户端

    作业 1 搭建TCP服务器 客户端 2 搭建UDP服务器 客户端 TCP服务器 include
  • 关于Java锁的面试总结

    面试过程中 也被问过几次关于Java中锁的问题 面试官一般是这么问 你了解Java中的锁吗 有几种 都有什么区别 讲一讲 大致可以分为这几点 锁是什么 有什么用 有哪几种锁 锁的区别 一 锁是什么 有什么用 锁主要用来实现资源共享的同步 只
  • Java实战项目(一)---编写聊天室程序

    刚开始学java 参考 java从入门到精通 这本书 学到网络程序设计基础这一章节 尤其与其他计算机进行通信 觉得还挺有意思的 所有深入地试试做一个小程序 聊天室程序 在代码中加入我自己的理解和困惑 希望能和大家一起探讨 每行的代码基本都有