当前位置: 首页 > news >正文

基于JAVA的TCP网络QQ聊天工具系统

目 录
1 功能设计 1
1.1功能概述 1
1.2功能模块图 1
2 逻辑设计 2
3 界面设计 4
3.1注册界面: 4
3.2登录界面 5
3.3好友列表页面 5
3.4好友聊天页面 6
3.5服务器界面 7
4 各模块详细设计 7
4.1登录模块 7
4.2注册模块 9
4.3聊天模块 10
4.4数据库工具类 12
4.5封装的数据交换类 12
5 系统测试 13
6 主要问题解决过程 15
7 作品总结 16
1.1功能概述
该系统是基于JAVA语言开发的一款网络聊天工具,通过Socket实现TCP编程,使用多线程实现了多客户端的连接。模仿腾讯QQ的界面,功能较为简单,但是使用了最基本的网络编程技术,如socket、tcp、I/O阻塞、多线程、MySQL数据库等。
该系统实现了用户的注册、登录以及与好友聊天的功能。
用户注册:系统随机生成账号,用户按照要求填入相应的信息。
用户登录:用户根据自己的账号和密码进行登录。
好友聊天:登录成功后,点击好友列表中的好友进行聊天。
6 主要问题解决过程
1)如何判断该好友是否在线?
最后一节课的课程分享,5班的同学在他的课程设计中使用了数组对登录的用户进行了记载,0代码不在线,1代表在线。在这里,我使用了相同的处理方式,将所以已经成功登录的用户SocketThread加入到HashMap集合中,SocketThread中记录了所有成功连接的socket实体类。
2)消息只能接收一次
使用while循环,时刻监听socket发送的数据,I/O阻塞接受客户端的消息。
3)验证登录和验证注册的逻辑使用了同一个。
一开始写好了登录的验证,后来实现注册时,在想注册和登录不就是返回结果相反吗?登录时是通过服务器查询数据库中存在该账号才允许登录,而注册验证是查询数据库后没有该用户才允许注册,所以直接调用了同一个方法。后来注册时有时可以,有时出现问题,当时没有仔细想,后来才发现,本文转载自http://www.biyezuopin.vip/onews.asp?id=14869返回结果是相反,但是验证注册不需要密码啊,只需要查询数据库中是否有该用户即可,如果使用登录的验证进行注册验证,那用户账号一样,密码不一样,同样可以允许注册了。
将注册的验证和注册的完成操作单独拿出,bug解决。
4)如何将不同的请求进行集中操作?
Java中的泛型可以处理不同数据的传入,但是由于平时使用的不多,对于泛型并不能彻底为我所用。最后封装了一个CommandTranser对象,实例化客户端时,通过sendData(CommandTranser msg)方法向服务器发送数据,然后通过getData()方法获得数据库返回的结果。
5)如果好友不在线,发送的消息怎么处理?
一开始自己想,只要好友不在线,弹出系统提示就足够了,不需要再将消息进行处理,可以在运行时出现了问题。没有想到好的解决办法,自己的处理方式是当好友不在线时,将该消息的发送方和接收方都设置为了自己。其实后来想想,如果实现了在线好友列表,在未发送消息之前,就可以知道好友是否在线,该问题就迎道而解。

package cn.edu.ldu.ui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import cn.edu.ldu.socket.Client;
import cn.edu.ldu.socket.ClientThread;
import cn.edu.ldu.util.CommandTranser;

/**
 * 聊天对话框
 */
public class ChatUI extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;
	private JTextArea chat_txt;
	private JTextField message_txt;
	private JButton send_btn;
	private JPanel panel;
	private String owner;
	private String friend;
	private Client client;
	private ClientThread thread;// 接收信息线程

	public ChatUI(String owner, String friend, Client client) {
		this.owner = owner;
		this.friend = friend;
		this.client = client;
		init();
		setTitle("与" + friend + "聊天中");
		setSize(350, 350);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setVisible(true);
		// 开启客户端接收信息线程
		thread = new ClientThread(client, chat_txt);
		thread.start();
	}

	private void init() {
		// TODO Auto-generated method stub
		setLayout(new BorderLayout());
		panel = new JPanel();
		message_txt = new JTextField(20);
		send_btn = new JButton("发送");
		panel.add(message_txt);
		panel.add(send_btn);
		chat_txt = new JTextArea();
		chat_txt.setEditable(false);
		chat_txt.add(new JScrollBar(JScrollBar.VERTICAL));
		add(chat_txt, BorderLayout.CENTER);
		add(panel, BorderLayout.SOUTH);
		send_btn.addActionListener(this);
		// 添加窗口关闭事件
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				thread.setOnline(false);
			}

			@Override
			public void windowClosed(WindowEvent e) {
				// TODO Auto-generated method stub
				thread.setOnline(false);
			}
		});
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		// 如果点击了发送按钮
		if (e.getSource() == send_btn) {
			Date date = new Date();
			SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss a");

			String message = "你说:" + message_txt.getText() + "\t"
					+ sdf.format(date) + "\n";
			// 在本地文本区追加发送的信息
			chat_txt.append(message);
			// msg为客户端向服务器发送的数据
			CommandTranser msg = new CommandTranser();
			msg.setCmd("message");
			msg.setSender(owner);
			msg.setReceiver(friend);
			msg.setData(message_txt.getText());

			client.sendData(msg);
			// 发送信息完毕 写信息的文本框设空
			message_txt.setText(null);
		}
	}

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关文章:

  • 【WLAN】【调试】netsh wlan常用命令使用说明
  • 教程图文详解 - 网络安全(第八章)
  • Python数据分析案例08——预测泰坦尼克号乘员的生存(机器学习全流程)
  • 计算机四级——操作系统原理常用知识点个人总结(上)
  • 【学姐面试宝典】—— 前端基础篇Ⅰ
  • c++之二叉树
  • 字符串训练赛
  • Android性能优化之【启动优化】
  • Java 集合与数据结构 · 接口 interfaces ·Collection 常用方法 · Map 常用方法
  • 面试面不过?大厂面试官是这样说的···
  • 秒懂YUV444/YUV422/YUV420计算(二十九)
  • 模方重大更新,支持3ds max、新版大疆数据、匀色、多原点数据等
  • 论文教程之 138位科研工作者分享如何(认真地)阅读一篇科学论文
  • MVC、MVP、MVVM三种模式的介绍及区别
  • 注意力机制综述学习记录
  • 【Amaple教程】5. 插件
  • Java IO学习笔记一
  • JAVA多线程机制解析-volatilesynchronized
  • PAT A1050
  • PhantomJS 安装
  • React Transition Group -- Transition 组件
  • 浮动相关
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 开发基于以太坊智能合约的DApp
  • 使用 QuickBI 搭建酷炫可视化分析
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 一个项目push到多个远程Git仓库
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 在Mac OS X上安装 Ruby运行环境
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • 《码出高效》学习笔记与书中错误记录
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​VRRP 虚拟路由冗余协议(华为)
  • ​虚拟化系列介绍(十)
  • $jQuery 重写Alert样式方法
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (C++)八皇后问题
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (ZT)出版业改革:该死的死,该生的生
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (三) diretfbrc详解
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (一)基于IDEA的JAVA基础1
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET Core中的去虚
  • .net 获取url的方法
  • .net 验证控件和javaScript的冲突问题
  • .net项目IIS、VS 附加进程调试
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • @test注解_Spring 自定义注解你了解过吗?