基于 Java+MySQL实现TCP聊天工具
基于 TCP 的 QQ 聊天工具
1 功能设计
1.1 功能概述
该系统是基于JAVA语言开发的一款网络聊天工具,通过Socket实现TCP编程,使用多线程实现了多客户端的连接。模仿腾讯QQ的界面,功能较为简单,但是使用了最基本的网络编程技术,如socket、tcp、I/O阻塞、多线程、MySQL数据库等。
该系统实现了用户的注册、登录以及与好友聊天的功能。
用户注册:系统随机生成账号,用户按照要求填入相应的信息。
用户登录:用户根据自己的账号和密码进行登录。
好友聊天:登录成功后,点击好友列表中的好友进行聊天。
1.2 功能模块图
该系统主要分为客户端还有服务器两个模块,具体的功能模块图如下图 1.1 所示。
图 1.1 功能模块图
2 逻辑设计
1、系统整体逻辑:
本系统由客户端响应用户的操作,通过封装对象实例化客户端,将请求发送给客户端,由客户端去执行相对应的数据库操作,将查询结果返回给服务器,服务器再执行响应的请求结果,图2.1所示
图 2.1 系统整体逻辑图
2、注册功能实现逻辑:
用户通过客户端进行账号的申请,客户端将注册的 User 对象信息封装为 CommandTranser 对象,通过实例化一个客户端,经过 sendData(CommandTransermsg)方法向服务器发送数据,服务器根据传来的注册请求和 username 去执行相应的数据库操作进行校验,由 msg.isfalg()返回结果,如果已存在该账号,则重新进行注册,未存在该账号,则可以进行登录。如图 2.2 所示
图 2.2 用户注册逻辑图
3、登录逻辑图:
用户通过客户端进行登录,客户端将带有账号和密码的登录指令封装为CommandTranser对象,然后实例化一个客户端,经过sendData(CommandTransermsg)方法向服务器发送数据,服务器根据传来的登录请求、username和password去执行相应的数据库操作进行校验,由msg.isfalg()返回结果,存在该用户则允许登录,否则需要重新输入正确的账号密码再次进行登录。如图2.3所示
图 2.3 用户登录逻辑图
4、聊天逻辑图:
图 2.4 聊天逻辑图
3 界面设计
3.1 注册界面:
该界面主要给用户提供注册新账号的功能。注册账号时除了自动生成的账号和输入的密码外,还需要进行身份的验证,其中包括真实姓名、性别、手机号。注册界面如图3.1.1所示
图 3.1.1 用户注册页面图
在客户端对输入的信息进行了校验,不允许输入的信息为空,并给出相应的系统提示信息,如图 3.1.2 所示。通过客户端向服务器发送的注册请求,服务器进行数据库的校验,同样返回系统提示信息。
图 3.1.2 系统提示图
3.2 登录界面
用户输入账号和密码后,服务器会将用户输入的信息进行校验,如果账号和密码输入有误,则会产生系统提示,让用户重新进行登录。如图3.2.1和图3.2.2所示
图 3.2.2 登录失败提示图
图 3.2.1 系统登录模块图
3.3 好友列表页面
用户输入正确的账号和密码后,完成登录请求,并打开好友列表界面,在列表顶部展示欢迎信息,如图3.3.1所示。添加了鼠标移入移出效果,如图3.3.2所示
如图3.3.1好友列表页面
如图3.3.2好友列表页面
3.4 好友聊天页面
用户在列表中双击鼠标,打开相应的聊天页面,如图3.4.1所示。在文本框中输入要发送的消息,如果用户不存在,会发出相应的系统提示,如图3.4.2所示。
图3.4.1聊天页面图
图3.4.2系统提示图
鼠标双击打开两个在线的好友,可以进行私聊功能,如图 3.4.3 所示。
图 3.4.3 私聊页面图
3.5 服务器界面
点击开启服务器后,新建一个线程开启服务器循环监听客户端的连接。如图3.5所示。
图 3.5 服务器页面图
4 各模块详细设计
4.1 登录模块
点击了登录模块后,首先判断账号和密码是否为空,然后封装为CommandTranser对象,向服务器发送数据,服务器通过与数据库进行比对来验证账号密码。
客户端获取用户输入的信息以及发送请求的代码如下:
服务器 Userservice 类操作数据库对登录进行验证,如果账号和密码正确,则返回 true,否则返回 false。实现代码如下:
如果登录成功,则将生成一个 SocketThread 对象,包括一个 socket,一个用户账号,将该 SocketThread 加入到 HashMap<String,Socket> 集合中,并且开启此用户的接收线程。代码如下:
HashMap<String,Socket> 用于记录所有已经成功登录的客户端。代码如下:
4.2 注册模块
客户端获取用户输入的信息后,将用户信息封装为User对象,将请求封装为CommandTranser对象,发送给服务器。代码如下:
服务器根据发送的请求,在 UserService 类中 checkregistUser(Useruser)先进行账号的验证操作,查询该账号是否已经存在。代码如下:
如果返回 false,则说明该账号未注册,允许用户进行注册,然后 UserService 类中的 register(Useruser)完成用户的注册。
4.3 聊天模块
一旦聊天功能启动,为每一个用户开启一个线程,通过I/O阻塞,client.getData()接收服务器发送的数据,如果服务器处理数据成功,接收消息,否则弹出该好友不在线的系统提示信息。
客户端获取消息内容、发送方和接收方,通过CommandTranser向服务器发送数据,代码如下:
服务器时刻监听客户端发送的消息,并调用 CommandTranserexecute(CommandTransermsg)方法传入 message 进行处理,如果处理成功,则可以向该好友发送消息,如果服务器处理信息失败,信息发送给自己,代码如下:
服务器对发送的消息进行处理,判断好友是否在线,然后将 msg 返回。代码如下:
服务器将所有的操作做完后,客户端再通过 getData()接收从服务器返回的数据,并在聊天界面中进行展示,代码如下:
4.4 数据库工具类
Dbhelpher为连接数据库的工具类,用户加载数据库驱动,连接数据库。
4.5 封装交换数据类
该类主要是客户端与服务器交换的数据,其中包括发送者、接受者、传递的请求数据、服务器需要做的指令以及处理结果。
代码如下:
5 系统测试
1.用户注册的测试,如果已经存在该账号,会出现系统提示,并重新生成号码并注册。否则注册成功。
图 5.1.2 注册成功系统提示图
图 5.1.1 注册失败系统提示图
2.用户输入账号和密码后,服务器会将用户输入的信息进行校验,如果账号和密码输入有误,则会产生系统提示,让用户重新进行登录。如图 5.2.1 和图 5.2.2 所示
图 5.2.2 登录失败提示图
图 5.2.1 系统登录模块图
3.用户输入正确的账号和密码后,完成登录请求,并打开好友列表界面,在列表顶部展示欢迎信息,如图 5.3.1 所示。添加了鼠标移入移出效果,如图 5.3.2 所示
如图5.3.2好友列表页面
如图5.3.1好友列表页面
4.用户在列表中双击鼠标,打开相应的聊天页面,如图 5.4.1 所示。在文本框中输入要发送的消息,如果用户不存在,会发出相应的系统提示,如图 5.4.2 所示。
图5.4.1聊天页面图
图5.4.2系统提示图
鼠标双击打开两个在线的好友,可以进行私聊功能,如图 5.5.1 所示。
图 5.5.1 私聊页面图
6 主要问题解决过程
1)如何判断该好友是否在线?
最后一节课的课程分享,5 班的同学在他的课程设计中使用了数组对登录的用户进行了记载,0 代码不在线,1 代表在线。在这里,我使用了相同的处理方式,将所以已经成功登录的用户 SocketThread 加入到 HashMap 集合中,SocketThread 中记录了所有成功连接的 socket 实体类。
2)消息只能接收一次
使用 while 循环,时刻监听 socket 发送的数据,I/O 阻塞接受客户端的消息。
3)验证登录和验证注册的逻辑使用了同一个。
一开始写好了登录的验证,后来实现注册时,在想注册和登录不就是返回结果相反吗?登录时是通过服务器查询数据库中存在该账号才允许登录,而注册验证是查询数据库后没有该用户才允许注册,所以直接调用了同一个方法。后来注册时有时可以,有时出现问题,当时没有仔细想,后来才发现,返回结果是相反,但是验证注册不需要密码啊,只需要查询数据库中是否有该用户即可,如果使用登录的验证进行注册验证,那用户账号一样,密码不一样,同样可以允许注册了。
将注册的验证和注册的完成操作单独拿出,bug 解决。
4)如何将不同的请求进行集中操作?
Java 中的泛型可以处理不同数据的传入,但是由于平时使用的不多,对于泛型并不能彻底为我所用。最后封装了一个 CommandTranser 对象,实例化客户端时,通过 sendData(CommandTransermsg)方法向服务器发送数据,然后通过 getData()方法获得数据库返回的结果。
5)如果好友不在线,发送的消息怎么处理?
一开始自己想,只要好友不在线,弹出系统提示就足够了,不需要再将消息进行处理,可以在运行时出现了问题。没有想到好的解决办法,自己的处理方式是当好友不在线时,将该消息的发送方和接收方都设置为了自己。其实后来想想,如果实现了在线好友列表,在未发送消息之前,就可以知道好友是否在线,该问题就迎道而解。
7 作品总结
1)系统整体
好几个周的努力,几天晚上的熬夜,该网络聊天工具基本算是完成,实现了用户的注册、登录以及好友之间的聊天功能。
2)系统亮点
该网络聊天工具虽然简单,但是其中之间夹杂了不少的逻辑。一开始自己想把登录、注册的验证只在客户端与数据库之间进行,仔细一想,那不就是上学期的大作业了嘛,不能体现网络编程的思想,所以将所有的请求处理放在服务器,虽然给自己带来了很大的困难,不过总之算是完成。
3)系统不足
好友之间的聊天,聊天内容局限性太大,内容太单一,只能进行文本消息的发送和接收,不能发送图片、文件。
网络的安全问题以及数据库的安全问题在该系统中并没有得到体现。
随机生成的账号时就确保该账号未曾注册过,而并不是单击注册之后再进行校验。
4)系统未来展望
在好友列表界面,有一个在线好友功能,未有实现,是否可以跟随着服务器的启动与关闭,创建和删除一个在线好友列表的数据库表。
增强系统的功能性与实用性,可以实现图片、文件、语音等的发送。
加强系统的安全性,对用户信息进行加密。
本学期的网络编程课算是结束,可是学习的路程还没有结束,课上的一些知识点,还不能让自己很轻松的驾驭。但是这一学期的学习,弥补了上学期 Java 课程中网络一章的不足,收获了很多,也接触到了很多特别有意思的地方,但是还有很多需要自己再继续学习下去,继续深入下去,路漫漫其修远兮,吾将上下而求索。一学期,也感谢董老师带来的激情与付出。