(2009届)

本科生毕业设计(论文)

基于Java的网络通信系统设计与实现

学 院、系:

计算机与通信学院

专 业:

通信工程

学 生 姓 名:

班 级:

学号

指导教师姓名:

职称

最终评定成绩

2009年6 月

摘 要

在网络越来越发达的今天,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的聊天工具越来越多,例如,国外的ICQ、国内腾讯公司开发的OICQ。随着网络聊天一类的聊天系统的发展日新月异,因此产生了制作一个类似QQ的网络聊天工具。Java是一种程序设计语言,它具有简单的、完全面向对象以及与平台无关的结构,也具有可移植性、高性能和安全性,并提供了多线程的功能,而Java语言最大的成功之处在于它的平台无关性和具有强大的网络编程功能,基于Java网络编程的强大功能,本人将用Java编写一个网络聊天系统。

论文首先论述了系统的开发背景,并对所用到的开发工具与关键技术做了简单的介绍。接着对系统的研究意义,研究现状及设计目标进行分析,通过对系统需求和可行性进行分析,确定了系统的功能模块,并画出相应的功能结构图、模块图和数据流图。其次按系统总体设计的结果,对系统中的数据库进行结构设计。

一般来说,聊天工具大多数由客户端程序和服务器程序,外加服务器端用于存放客户数据的数据库组成,本系统采用客户机/服务器架构模式,通过Java提供的Socket类来连接客户机和服务器并使客户机和服务器之间相互通信,由于聊天是多点对多点的,而Java提供的多线程功能,用多线程可完成多点对多点的聊天。数据库管理系统用SQL Server2000,完成并通过JDBC-ODBC桥访问数据库。聊天系统完成后将可进行多人对多人的聊天,对好友进行添加、删除,对新用户的注册,发送消息、接受消息,传输文件等功能。界面设计细分化,方便使用者操作和理解。服务器实现了查询和修改等功能,程序逻辑联系较紧密。

关键词:JAVA,C/S,SQL Server 2000, 多线程, 数据库管理系统

ABSTRACT

More and more developed in the network today, people rely on more and more networks, and can not leave with out it. This caused the chat materials become more numerous, as the overseas ICQ system, the OICQ system that invented by Tencent Co., and so on. So we create a network chat medium just like the QQ.Java is a programming language with the simple construction which is completely object-oriented 。Java also possess the portability, high performance and security, and provide the multi – thread function. The best success is its and its strong network programming function, base on this, I will use Java to write a network chat system.
Firstly, the paper discussed the development background of the system, and made a briefly introduction to the development tool and key technologies. Then analyzed the system’s research significance , research present situation and project objective .According to the requirement analysis and feasibility analysis ,it can confirm the system’s functional module and draw corresponding functional configuration chart ,module chart and data stream chart. On the basis of the result of system designing, the paper design database by structured design method.

Generally speaking, most chat medium consist the client program, server program and the server which is use to content the database. This system adopt client/server pattern and the Socket class provide by Java to communicate the client and server. Because of chat is many to many, the multithreading function can implement the many-many chat, database management system use SQL Server2000 and JDBC-ODBC bridge to visit the database.
When chat system is achieved, it can possess functions like chat in a many-many way, add and delete the intimate, the new user’s registration, and sending and receiving message, transferring files and so on. The refinement of interface designing would facilitate user operation and understanding. The contact surface has the thin differentiation designs; modules have realized the functions such as inquiry, revision and so on. The logic relationship in this program is closed.

Keyword: Java, Multithreading, Client/Server, SQL Server2000,

Database Management System

目 录

第1章 绪论1

1.1 课题选择的背景1

1.2 课题选择意义1

1.3 系统开发技术简介2

1.3.1 Java简介2

1.3.2 JDBC技术简介2

1.3.3 数据库Microsoft SQL-Server 2000 简介4

1.3.4 多线程介绍4

第2章 系统分析6

2.1 系统需求6

2.1.1 系统的特点分析6

2.1.2 网络聊天系统需要解决的问题6

2.2 系统设计思想6

2.3 系统实现功能分析7

2.4 系统开发及运行环境7

第3章 系统总体设计8

3.1 总体构架8

3.2 系统整体功能8

3.3 系统模块功能设计9

第4章 数据库设计12

4.1 系统E-R图12

4.2 数据字典12

4.3 各个数据表的创建12

4.4 数据库的连接13

第5章 系统实现与编码15

5.1 服务器功能模块的设计15

5.1.1 Socket和ServerSocket介绍15

5.2 服务器功能模块的实现16

5.2.1 多线程服务器模块实现16

5.2.2 在线用户管理模块实现18

5.2.3 部门管理模块实现20

5.2.4 用户管理模块实现21

5.2.5日志管理模块实现22

5.3协议设计与实现23

5.3.1 协议规则23

5.3.2 协议实现24

5.4客户端功能模块的设计与实现27

5.4.1 登陆认证模块27

5.4.2 主界面模块27

5.4.3 聊天模块28

5.4.4 文件传输模块29

第6章 系统测试33

6.1 系统测试概述33

6.1.1 测试目标33

6.1.2 测试实例研究与选择33

6.1.3 系统测试环境33

6.2 测试内容34

6.2.1 服务器模块测试34

6.2.2 客户端模块测试34

6.2.3 平台兼容性测试35

6.3 测试结果分析评价35

结 论36

参考文献37

致 谢38

第1章 绪论

1.1 课题选择的背景

信息时代的到来引发了一场知识和信息革命,计算机和现代网络技术的广泛应用极大地促进了社会经济的发展,同时也带来了一些新兴产业的发展,比如聊天软件。随着计算机网络日新月异的发展,人们的交流方式越来越多,传统的交流方式已经难以满足人们的交流的需求了,网络聊天已经慢慢成为人们生活的一部分,呈现出良好的势头和广阔的发展前景。在互联网上即时的和好友取得联系,已经成为当今社会人们主流的联系方式。同时,即时通信系统对现代企业也有着重大意义,它能实现快速人际交流、数据共享,从而提高效率和生产力。实时通信为诸多企业开拓了网络应用的新领域。自从它诞生以来,以实时交互、资费低廉等优点,受到广大个人用户的喜爱,已经成为网络生活中不可或缺的一部分。越来越多的企业已开始认识到即时通信工具能够带来极高的生产力,并借助它的应用,来提高业务协同性及反馈的敏感度和快捷度。网上聊天系统是为人们之间进行交流和联系提供的一个平台。通过提供完善的网上聊天系统服务,可以达到增进彼此之间的了解,增进人与人之间的感情交流。因此,两台计算机之间进行即时通讯、发送文件等交流方式已经成为必然潮流。于是出现了QQ、UC 等聊天工具,然而QQ、UC 等聊天工具虽然方便、实用,但是,娱乐功能太多,有很多吸引人的娱乐功能,从一定程度上来说,是一种娱乐工具,不能作为用于即时通讯的专用工具。目前,用于实现单一的即时通讯的软件实在太少,为此,我们决定开发一个专用于实现多台计算机之间即时通讯的软件,以方便多台计算机之间信息的快速交流。

1.2 课题选择意义

计算机越来越成为我们生活中的重要工具,自从1968年世界上第一个计算机网络--ARPA网(美国国防部高级研究计划网)投入运行以来,计算机网络技术在全世界范围内迅速发展,犹如雨后春笋,各种网络纷纷涌现。不同国家的计算机网络相互连接,形成跨国计算机网络,促进了世界各国之间的科技、文化和经济交流。在电子商务的应用中,计算机网络作为基础设施,将分散在各地的计算机系统连接起来,使得计算机之间的通讯在商务活动中发挥了重要的作用,从此计算机的作用不再那么单调,现在Internet把几乎全球的服务器相互连接起来,这样不仅使网络上的计算机之间进行相互访问并下载对自己有用的资源,还可以用来写信、听音乐、看电视、通过可视电话进行通信,通过Internet网进行信息查询、网上购物等。计算机正在改变我们的通信、工作和娱乐的方式。

1.3 系统开发技术简介

1.3.1 Java简介

Java是由Sun Microsystems公司于1995年5月推出的Java程序设计语言(以下简称Java语言)和Java平台的总称。它以C++为基础,但是却是一个全新的软件开发语言。Java是一个简单,面象对象,分布式,解释性,强壮,安全,与系统无关,可移植,高性能,多线程和动态的语言-------这是 Sun给Java的定义。

Java平台由Java虚拟机(Java Virtual Machine)和Java 应用编程接口(Application Programming Interface、简称API)构成。Java 应用编程接口为Java应用提供了一个独立于操作系统的标准接口,可分为基本部分和扩展部分。在硬件或操作系统平台上安装一个Java平台之后,Java应用程序就可运行。现在Java平台已经嵌入了几乎所有的操作系统。

Java是一种简单的,面向对象的,分布式的,解释型的,健壮安全的,结构中立的,可移植的,性能优异、多线程的动态语言。Java 对开发者具有不可估量的价值,使他们可以:

  • 在一个平台上编写软件,然后即可在几乎所有其他平台上运行
  • 创建可在 Web 浏览器和 Web 服务中运行的程序
  • 开发适用于在线论坛、存储、投票、HTML 格式处理以及其他用途的服务器端应用程序
  • 将采用 Java 语言的应用程序或服务组合在一起,形成高度定制的应用程序或服务
  • 为移动电话、远程处理器、低成本的消费产品以及其他任何具有数字核心的设备编写强大而高效的应用程序
    Sun公司的口号就是"网络就是计算机",Java能使所有东西从桌面计算平稳的转变为基于网络的计算,它是专门为此而建立的,并显然是为了完成这个任务而来的。使用Java,我们可以相对轻松的一天编写一个有条理的网络程序。今天,Java的网络功能正在飞跃发展,不断有新的特性增加到这个有价值的基础上,JavaSoft实验室正在不断努力使Java更加完善。
    1.3.2 JDBC技术简介
    JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,JDBC是Java的开发者Sun的Javasoft公司制定的。它由一组用Java语言编写的类和接口组成。JDBC为工具/数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯 Java API 编写数据库应用程序。
    有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事。换言之,有了JDBC API,就不必为访问Sybase数据库专门写一个程序,为访问Oracle数据库又专门写一个程序,或为访问Informix数据库又编写另一个程序等等,程序员只需用JDBC API写一个程序就够了,它可向相应数据库发送SQL调用。同时,将Java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序,只须写一遍程序就可以让它在任何平台上运行,这也是Java语言“编写一次,处处运行”的优势。
    Java数据库连接体系结构是用于Java应用程序连接数据库的标准方法。JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型。作为API,JDBC为程序开发提供标准的接口,并为数据库厂商及第三方中间件厂商实现与数据库的连接提供了标准方法。JDBC使用已有的SQL标准并支持与其它数据库连接标准,如ODBC之间的桥接。JDBC实现了所有这些面向标准的目标并且具有简单、严格类型定义且高性能实现的接口。
    Java 具有坚固、安全、易于使用、易于理解和可从网络上自动下载等特性,是编写数据库应用程序的杰出语言。所需要的只是 Java应用程序与各种不同数据库之间进行对话的方法。而 JDBC 正是作为此种用途的机制。
    ODBC在Windows系列平台应用程序中和JDBC在Web和Internet应用程序中的作用的作用类似。ODBC(OpenData Base Connectivity),称为开放式数据库互联技术,是由Microsoft公司倡导并得到业界普遍响应的一门数据库连接技术。 JDBC现在可以连接的数据库包括:xbase、Oracle、Sybase、Aceess以及Paradox等。
    JDBC的工作机制 :JDBC定义了Java语言同SQL数据之间的程序设计接口。JDBC有一个非常独特的动态连接结构,它使得系统模块化。使用JDBC来完成对数据库的访问包括以下四个主要组件:Java的应用程序、JDBC驱动器管理器、驱动器和数据源。
    JavaSoft公司开发了JDBC API,JDBC API是一个标准统一的SQL数据存取接口。 JDBC在Internet中的作用与ODBC在Windows系列中的作用类似。它为Java程序提供了一个统一缝地操作各种数据库的接口,程序员编程时,可以不关心它所要操作的数据库是哪个厂家的产品,从而提高了软件的通用性,而且在Internet上确实无法预料你的用户想访问什么类型的数据库。只要系统上安装了正确的驱动器组,JDBC应用程序就可以访问其相关的数据库。
    1.3.3 数据库Microsoft SQL-Server 2000 简介
    Microsoft SQL-Server(简称 SQL-Server)是微软公司推出的一个高性能的关系型数据库管理系统,随着其产品性能的不断提高,使之在数据库系统领域中占有重要地位。Microsoft SQL-Server 2000是继SQL-Server 6.5和SQL-Server 7.0以后,推出的又一改进的关系型数据库管理系统,它能使用户快捷地管理数据库和开发应用程序。SQL-Server 2000使用了最先进的数据库结构,与Windows DNA紧密集成,具有强大的Web功能,它可以利用高端硬件平台以及最新网络和存储技术,可以为最大的Web站点和企业应用提供优良的扩展性和可靠性,使用户能够在Internet领域快速建立服务系统,为占领市场赢得宝贵的时间。同时,SQL-Server 2000还为用户提供了重要的安全性功能的增强,为用户的数据安全提供了可靠的保证。另外,SQL-Server 2000在数据库服务器自动管理技术方面处于数据库领域的领先地位,它可以使用户免去繁琐复杂的工作量,从而又精于处理更重要的问题,使系统在商业战略上占得先机。SQL-Server 数据库系统特点:与Internet高度集成;高伸缩性和适应性;企业级数据库功能强。
    存储过程是存储在服务器上的预先编译好的SQL语句,可以在服务器上的SQL Server环境下运行[12]。使用存储过程有如下的好处:执行时间短;客户/服务器开发分离;安全性高。SQL-Server 2000工具界面与标准Windows 界面非常类似,具有菜单栏、图标、树状视图控件、单选按钮等。这些熟悉的界面使以前即使从没有见到过这些应用程序的人也能够很快地了解一些基本的功能。
    1.3.4 多线程介绍
    Java 支持内置多线程编程。多线程程序包括两条或两条以上并发运行的部分。程序中每个这样的部分都叫一个线程,每个线程都是独立的执行路径。因此,多线程是多任务处理的一种特殊形式。
    多任务处理有两种截然不同的类型:基于进程的和基于线程的。进程本质上一个正在执行的程序。因此,基于进程的多任务处理的特点是允许你的计算机同时运行两个或更多的程序。举例来说,基于进程的读任务处理使你在运行文本编辑器的时候可以同时运行Java 编译器。在基于进程的多任务处理中,程序是调度程序多分派的最小代码。也就是说,进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源。
    在基于线程的多任务处理环境中,线程是最小的执行单位。线程是进程中的一个单一的连续控制流程。一个进程可以拥有多个线程。这意味着一个程序可以同时执行两个或多个任务的功能。例如,一个文本编辑器可以在打印的同时格式化文本。所以,多进程程序处理大局问题,而多线程程序处理细节问题。
    多线程程序比多进程程序需要更少的管理开销。进程是重量级的任务,需要分配它们自己独立的地址空间。进程间通信是昂贵和受限的。进程间的转换也是很需要花费的。另一方面,线程是轻量级的选手,它和进程一样拥有独立的执行控制,由操作系统负责调度。区别在于线程没有独立的存储空间,而是和所属进程的其他线程共享一个存储空间,因此,线程间通信是容易的,线程间的转换也是低开销的。当Java 程序使用多进程的任务处理环境时,多进程的程序不受Java 的控制,而多线程则受控于Java。
    多线程可以帮会你写出CPU 最大利用率的高效程序,因为空闲时间保持最低。这对Java 运行的交互式的网络互联环境至关重要,因为空闲时间是公共的,举个例子来说,网络的数据处理传输速率远低于计算机处理能力,本地文件系统资源的读写速度远低于CPU 的处理能力,当然,用户输入也比计算机慢的多。在传统的单线程环境中,你的程序必须等待每一个这样的任务完成以后才能执行下一步—尽管CPU 有很多空闲时间。多线程是你能够获得并充分利用这些空闲时间。
    ·多线程编程简单,效率高(能直接共享数据和资源,而多进程却不能)
    ·适合于开发多种交互接口的程序
    ·减轻编写交互频繁,涉及面多的程序的困难
    在本系统中,设置后台线程处理服务器和客户程序的通信。服务器资源以轻量级的线程提供,和多个客户线程并发连接通信。这样可以减轻服务器端的开销,同时保证了多个用户端连接能够得到快速而高效的服务。
    第2章 系统分析
    2.1 系统需求
    随着网络的迅速发展,通过即时通讯工具进行相互交流,沟通会对用户带来很多的方便,像现在很流行的QQ、MSN、UC等,它们为用户们之间的沟通带来很多的方便的,但是这些即时工具在企业或者学校禁止用户访问外网的时候,这些即时的通信工具就不能使用了,用户之间就不能很方便的沟通交流了,可以通过自己设计一个即时通讯工具,自己建立服务器,放在内部网络,在用户不能访问外部网络的时候,可以很方便用户之间进行沟通交流。
    2.1.1 系统的特点分析
    基于JAVA的网络聊天系统基于C/S 模式实现,采用Java 语言编写。所有用户都通过服务器端中转消息,这也是现有大多数聊天系统所采用的模式。本系统真正地实现了多点聊天的功能,可以在多点间快速传递信息。同时,它体积小,功能单一,界面简洁美观,容易上手,只要简单阅读服务器端和客户端的帮助文档即可完全掌握它的使用方法,同时该系统是网络聊天,特别是局域网聊天不可多得的好帮手。
    2.1.2 网络聊天系统需要解决的问题
    首先,网络聊天系统是一个比较复杂的系统,良好的架构设计非常的重要:C/S 模式是较为成熟的软件运行模式,基于局域网设计,运行速度快,安全性高,为当今主要的软件所采用的模式。不好的架构会在系统实现或者维护阶段系统的扩展带来很多麻烦。
    其次,服务器的承载能力,如何处理多个用户的同时登录和请求,好的设计会使系统在很多并发用户登录的时候不至于系统崩溃。
    最后,服务器和客户端的通信协议制定比较困难,如何制定一套简单,并且易于客户端和服务器之间理解的通信规则非常重要,否则会在服务器和客户端通信设计的时候带来很多的问题。
    2.2 系统设计思想
    本系统的设计思路如下:
  1. 系统采用模块化设计,针对不同的应用设计不同的模块,并对这些模块都进行集中式管理,作为应用程序有较强的可操作性和扩展性。
  2. 合理的数据流设计,在应用系统设计中,相对独立的模块间以数据流相互连接,使各模块间的耦合性较低,方便系统运行,提高系统安全性,尽量保证低耦合,高内聚。
  3. 采用封装的思想,根据模块的不同情况进行类的封装,并重用各个模块,并合理利用各种设计模式,为以后维护带来方便。

2.3 系统实现功能分析

本次设计主要实现了以下几个功能:

● 客户端功能设计如下:

  1. 身份认证,该模块主要实现用户的登陆认证,以及服务器代理IP和端口的设置,并检查数据的合法性。
  2. 聊天功能,该模块主要用Socket实现不同用户之间消息的的发送,并且不仅仅传文本格式的数据,也可以传输图片,需要自己封装并自定义消息流,并能够识别显示。
  3. 文件传输,该模块主要实现不同用户之间进行文件的传输。

● 服务器端功能设计如下:

  1. 在线用户统计,该模块主要实现在线用户的查看显示,并可以控制其在线状态,强迫特定用户下线。
  2. 日志记录,该模块主要记录客户端用户上线、下线情况,并存储下来。
  3. 发布信息,该模块主要服务器可以发布系统信息,使客户端可以接收。

2.4 系统开发及运行环境

  1. 系统开发平台:本系统采用eclipse 及WINDOWS XP设计。
  2. 硬件环境:
    运行本系统的硬件基本要求如下:
    CPU:Intel P3及以上;
    内存:256MB及以上;
    硬盘:40GB及以上。
  3. 数据库管理系统软件:SQL Server 2000。

第3章 系统总体设计

3.1 总体构架

基于Java的网络聊天系统设计与实现主要考虑三个个方面的设计,即服务器模块设计,服务器客与客户端通信规则设计和客户端模块设计,本系统整体构架如图3.1所示。

java 框架 聊天系统 基于java的聊天系统_Java

图3.1 系统整体构架图

3.2 系统整体功能

基于JAVA的网络聊天系统分为服务器端和客服端,其中:

服务器端包括:在线用户管理模块,用户管理模块,部门管理模块,日志管理模块;

客服端包括:用户认证模块,主界面模块,聊天模块,文件传输模块。

系统整体功能设计如下图2.2所示

java 框架 聊天系统 基于java的聊天系统_java_02

图3.2 系统整体功能设计图

3.3 系统模块功能设计

整个系统分为3个模块,其中主要功能如下:

(一)服务器端模块

服务器端模块首先设计多线程来处理客户端的连接,当受到客户端请求的时候,建立一个新的线程来处理客户端的连接。并且在一个注册中心中登记该线程,并存储客户端用户的一些信息,方便服务器统计在线用户,以便与这些在线用户进行通信。除此之外,为了方便用户更好的操作和掌握服务器端,系统还设计四个管理服务器的模块,分别是在线用户管理模块,用户管理模块块,部门管理管理模块和日志管理模块。各个模块功能设计如下:

  1. 在线用户管理模块
    该模块主要实现在线用户管理,查看当前登陆账号的所有用户信息(在线用户的)。并且管理员有权限设置用户的在线状态,可以强制用户下线。同时添加一些辅助的功能,比如服务器发送一些系统公告信息等,这样有利于系统消息的及时发送。
  2. 用户管理模块
    该模块主要实现新用户的添加、注册用户的删除、修改和查看的功能,管理数据库中存储的用户信息。该模块可以对注册用户的信息(注册用户的编号,姓名,性别,头像,年龄,家庭住址,联系电话,注册时间爱你)进行修改以及查看,并且保证客户端使用这些用户信息登陆服务器。
  3. 部门管理模块
    该模块主要实现部门的添加、注册部门的删除、修改和查看的功能,管理数据库中存储的部门信息。该模块可以对注册部门的信息(部门名称,部门描述)进行修改以及查看。
  4. 日志管理模块

日志管理模块主要实现服务器运行状态信息,以及注册用户登陆的一些信息进行记录,管理员可以在需要的时候查看日志,监控服务器的一些状态,以及客户端一些用户的状态。

(二)协议规则模块

该模块主要实现服务器与客户端之间通信规则的制定。其具体思路是:在服务器使用Socket通信的时候,把服务器与客户端通信的信息封装为一个类对象,然后通过自己手动将这些类对象转化为输入流,并在另一端输出流,根据自己制定的规则逆序解析流,把流转化为类对象。实现服务器与客户端之间的通信。其中具体的表示信息要自己制定,比如登陆成功标示,失败标示,修改密码标示,聊天标示等,这些都需要自己通过一些数字标记。

(三)客户端模块

客户端模块主要实现,用户账号到服务器的认证,以及登陆之后与其他用户通信或者部门通信,除了简单文本聊天之外,也考虑用户之间文件传输的功能。其中客户端之间的通信,是在客户端之间搭建服务器,也即客户端自己建立SocketServer,并用多线程来处理对不同用户的聊天。用户之间文件传输也是通过搭建客户端之间的服务器来实现文件出传的,不需要通过服务器来实现信息的传输,可以减少延迟,也减少了服务器端的流量损失。但是在客户之间搭建连接的时候仍然需要通过服务器来实现一些简单的通知操作,实现客户端与客户端之间搭建其连接。因此客户端大体分四个模块,分别是用户认证模块,主界面模块,聊天模块和文件传输模块。各个功能模块设计如下:

  1. 用户认证模块
    可以模仿QQ登陆界面,输入用户名和密码,以及服务器IP和端口,实现账号和密码到服务器的认证,判断用户是否有权限登录主界面进行信息沟通。
  2. 主界面模块
    该模块主要实现类似QQ友好的界面,查看自己的信息,修改密码,显示好友列表组列表信息。使用Swing现有组建扩展制作合适的界面设计,并搭配后台功能。
  3. 聊天模块
    该模块主要实现不同用户之间信息的发送,如何实现点对点用户通信,多点用户通信,要考虑多线程的设计才可以实现。同时信息发送除了文本之外还要考虑其他信息格式比如图片之类。
  4. 文件传输模块
    实现不同用户之间多线程的文件传输。
    第4章 数据库设计
    4.1 系统E-R图
  1. E-R模型

基于网络聊天系统数据库E-R模型,如图 所示:

java 框架 聊天系统 基于java的聊天系统_java_03

图4.1 聊天系统E-R图

4.2 数据字典

  1. 用户表 (用户ID(主键),用户名,密码,用户密码,性别,头像ID,部门ID,年龄,电话号码,地址,注册时间,状态)。
  2. 分组信息表(分组ID(主键),分组名字,标记)。

4.3 各个数据表的创建

基于网络聊天系统数据库包括部门信息以及用户信息,部门信息表格和用户信息表格的设计结果如表4.1,表4.2所示:每个表格表示在数据库中的一个表。

表4.1部门信息表(T_DEPARTMENT)

列名

数据类型

可否为空

字段名称

字段大小

D_ID

VARCHAR

No null

分组ID

3

D_NAME

VARCHAR


分组名字

50

D_REMARK

VARCHAR


标记

100

表4.2 用户表(T_USER)

列名

数据类型

可否为空

字段名称

字段大小

U_ID

VARCHAR

Not null

用户ID

6

U_NAME

VARCHAR


用户名

50

U_PASSWORD

VARCHAR


用户密码

20

U_SEX

VARCHAR


性别

3

U_ICONID

INT


头像ID

4

U_DEPTID

VARCHAR


部门ID

3

U_AGE

INT


年龄

4

U_TEL

VARCHAR


电话号码

20

U_ADDRESS

VARCHAR


地址

100

U_REGTIME

DATETIME


注册时间

8

U_ISONLINE

INT


状态

4

4.4 数据库的连接

打开控制面板,找到管理工具,在选中数据源配置,进行ODBC数据源的配置其中主要的配置流程如下面图所示:

java 框架 聊天系统 基于java的聊天系统_java_04

图4.2 配置QQ数据源界面

java 框架 聊天系统 基于java的聊天系统_java_05

图4.3 配置QQ数据库界面

java 框架 聊天系统 基于java的聊天系统_服务器_06

图4.4 测试数据源连接

第5章 系统实现与编码

5.1 服务器功能模块的设计

5.1.1 Socket和ServerSocket介绍

Socket,简称套接字,用于实现网络上客户和服务器之间的连接。也就是说网络上两个或两个以上双工方式通信的进程之间总有一个连接,这个连接的端点成为套接字,套接字是在比较低的层次上通信的。

具体的说:一个服务器应用程序一般侦听一个特定的端口等待客户端的连接请求,当一个连接请求到达时,客户端和服武器端建立一个通信连接,在连接过程中,客户端被分配一个本地端口与一个socket建立连接,客户端通过写socket来通知服务器,以读socket中的信息,类似的服务器也获得一个本地端口,它需要一个新的端口号来侦听原始端口上的其他连接请求。服务器也通过它的本地端口连接一个socket,通过读写和客户端通信。

Socket程序的工作过程:

1、建立Socket连接:在通信开始之前由通信双方确认身份,建立一条专用的虚拟连接通道。

2、数据通信:利用虚拟连接通道传送数据信息进行通道。

3、关闭:通信结束时,再将所建的虚拟连接拆除。

实现套接字的服务端,需要使用ServerSocket 类。ServerSocket类是服务器程序的运行基础,它允许程序绑定一个端口号来监听客户端的请求,一旦产生客户端请求,它将接受这一请求,同时产生一个完整的Socket 连接对象。服务器绑定的端口必须公开,以便让客户端程序知道如何连接这个服务器。同时,作为服务器,它必须能够接收多个客户的请求,这就需要为服务器设置一个请求队列,如果服务器不能马上响应客户端的请求,要将这个请求放进请求队列中,等服务器将当前的请求处理完,会自动到请求队列中按照先后顺序取出请求进行处理。服务器的资源是有限的,这就导致它的最大连接数是有限的,通过ServerSocket 的构造函数可以指定这个最大连接数。如果不明

确指定这个连接数,默认最大连接数为50,也就是说,客户端的请求队列最大可以容纳50 个请求,当超过这个最大连接数时,用户的请求将不再会被响应。 利用SocketServer 也提供了一些方法,它们主要有:

accept() 返回一个“已连接”的Socket 对象

getInetAddress() 得到该服务器的IP 地址

getLocalPort() 得到服务器所侦听的端口号

setSoTimeout() 设置服务器超时时间

getSoTimeout() 得到服务器超时时间

服务器和客户端通过Socket简单通信框架下图所示。

java 框架 聊天系统 基于java的聊天系统_Java_07

图 5.1 服务器和客户端通过Socket简单通信框架

5.2 服务器功能模块的实现

5.2.1 多线程服务器模块实现

服务器模块核心功能是使用Socket Server实现多线程的服务器,针对每一个客户建立一个单独的线程处理客户端的请求。其具体思路是,首先建立Socket Server,并绑定服务器IP和某个未使用的端口。然后监听该端口,如果有客户端的Socket连接则建立一个客户端线程ClientThread类对象,有该对象处理该客户的一些请求,并在ClientThread中保存User Bean对象,该对象保存了用户的一些基本信息,比如账号、密码、年龄、是否在线等。如果服务器没有关闭Socket Server则服务器则一直处理客户端连接。其核心代码如下。

public class MessageServer extends Thread {
//服务器端SocketServer
private ServerSocket server;
private boolean isStop = false;
public MessageServer(int port) throws IOException {
server = new ServerSocket(port);
}
/**
* 消息服务
*/
public void run() {
Socket client;
try {
while (!isStop) {
//建立处理客户端连接的线程
client = server.accept();
(new ClientThread(client)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (server != null) {
try {
server.close();
} catch (IOException e1) {
// e1.printStackTrace();
}
}
isStop = true;
}
}
}

5.2.2 在线用户管理模块实现

该模块主要实现在线用户统计、多线程服务器的启动关闭、以及服务器发送系统公告等功能。其中在线用户统计是在客户端每次连接的时候服务器建立了ClientThread来单独处理某个客户请求,如果该客户登陆成功的话则在工具类PubValue中一个HashMap添加该用户信息,查看在线用户信息的时候,可以通过工具类PubValue来的HashMap读取在线用户列表。系统公告则是通过服务器根据在线用户列表,广播系统公告到每个客户端,实现信息的公布。其实核心代码如下:

private void login(Message message) throws IOException {
if (message.getType().equals(PackOper.LOGIN)) {
User user = (User) message;
List list = UserDaoFactory.getUserDao().selectId(user.getId());
if (list.size() > 0) {
User tempUser = (User) list.get(0);
if (tempUser.getPassword().equals(user.getPassword())) {
if (tempUser.getIsOnline() == Parameter.ONLINE) { message.setType(PackOper.LOGIN_ONLINED);
myObjectOut.writeMessage(message);
this.setStop();
return;
}
ServerUI.getInstance().getLogUI().addLog(
LogOper.getInstance().insertOnLineLog(tempUser));
//登录成功后
//先通知所有人
//再通知此用户
//再把自己加到线程组中
//接着更新数据库
//下载树给此用户
tempUser.setType(PackOper.LOGIN_SUCCEED);
tempUser.setIsOnline(pub.Parameter.ONLINE);
this.chatCompany(tempUser);
this.user = tempUser;
this.myObjectOut.writeMessage(tempUser);
PubValue.addUserThread(this.user.getId(), this);
UserDaoFactory.getUserDao().setOnline(tempUser.getId(),
Parameter.ONLINE);
ServerUI.getInstance().getOnLineUI().updateOnLine();
try {
Thread.sleep(10);
} catch (InterruptedException e1) {
// e1.printStackTrace();
}
// 登录成功后发送树
PubValue.company.setType(PackOper.ADD_COMPANY);
myObjectOut.writeMessage(PubValue.company);
list = DepartmentDaoFactory.
getDepartmentDao().select(null);
Iterator it = list.iterator();
while (it.hasNext()) {
message = (Message) it.next();
message.setType(PackOper.ADD_DEPARTMENT);
myObjectOut.writeMessage(message);
}
list = UserDaoFactory.getUserDao().select(null);
it = list.iterator();
while (it.hasNext()) {
message = (Message) it.next();
message.setType(PackOper.ADD_USER);
myObjectOut.writeMessage(message);
}
return;
}
}
message.setType(PackOper.LOGIN_DEFEATED);
myObjectOut.writeMessage(message);
this.setStop();
}
}

其实现效果如图所示:

java 框架 聊天系统 基于java的聊天系统_java 框架 聊天系统_08

图5.2 聊天服务器端界面

5.2.3 部门管理模块实现

该模块主要实现对部门进行管理,根据情况添加,删除或者修改部门等。其设计主要是通过SQL语句来操作数据库数据的。跟普通的管理系统设计思路一样。没有太多的算法,主要是SQL语句的构造,以及数据库操作的API函数的使用。其实现效果如图所示.

java 框架 聊天系统 基于java的聊天系统_服务器_09

图5.3 部门管理模块界面

5.2.4 用户管理模块实现

该模块类似于部门管理模块的设计,主要是针对用户的一些信息进行管理,根据需要添加、删除或者修改用户信息。其实现主要也是SQL语句的构造以及JDBC驱动提供函数的使用。比较复杂的部分设计主要体现界面的设计,如何使用Swing构造友好并且易于交互的界面需要花费一些时间。以及实现组合条件的用户查询,可以根据用户账号查询,或者所在部门查询,或者编号查询,或者根据这三个条件组合查询,这一功能比较复杂,如何根据不同的情况构造合适的SQL语句进行数据查询,显得很重要,否则粗略的设计会增加很多冗余代码。其整体实现效果如下图5.4所示。

java 框架 聊天系统 基于java的聊天系统_java_10

图5.4 用户管理界面

5.2.5日志管理模块实现

日志管理模块主要是监控服务器的一些状态,以及客户端用户登陆的情况。这些日志信息记录是通过工具类LogOper实现日志的记录。该类使用了设计模式中单例模式,保证服务器端在进行日志操作的时候只有一个实例在内存中进行日志的记录。其日志的存放路径主要是在系统目录下,其文件名为server.log。通过服务器UI界面查询日志信息也是通过读取该文件来查询日志记录的。其实现效果如下图5.5:

java 框架 聊天系统 基于java的聊天系统_java 框架 聊天系统_11

图5.5 日志管理模块界面

5.3协议设计与实现

5.3.1 协议规则

协议规则里主要用一些整数来表示服务器与客户端通信的时候包的类型。服务器可以按照这个规则来解析包,并根据包中的信息做出相应的操作。其标示的具体含义和定义规则下表5.1所示。

表5.1 协议规则表

标示名字

标示值

标示意义

LOGIN

10

登录包标识

LOGIN_SUCCEED

11

登录成功标识

LOGIN_DEFEATED

12

登录失败标识

LOGIN_ONLINED

13

已经在线标识

ADD_COMPANY

14

添加公司标识

ADD_DEPARTMENT

15

添加部门标识

ADD_USER

16

添加用户包标识

UPDATE_COMPANY

17

更新公司信息标识

UPDATE_DEPARTMENT

18

更新部门信息

UPDATE_USER

19

更新用户信息

DELETE_DEPARTMENT

20

删除部门

DELETE_USER

21

删除用户

CHAT_USER

22

私聊

CHAT_DEPARTMENT

23

部门聊天

CHAT_ALL

24

公司聊天

MESSAGE

25

公司通知

UPFILE

26

要求传送文件

UPFILE_FIAT

27

许可传送文件

SEND_DEFUSE

28

发送方取消

UPFILE_DEFUSE

29

不许可传送文件

DOWN_LINE

30

下线包

FORCEDOWN_LINE

31

强制下线包

UPPASSWORD

32

修改密码

UPPASSWORD_DEFEATED

33

原密码不对

UPPASSWORD_NEW_NULL

34

新密码为空

UPPASSWORD_SUCCEED

35

修改密码成功

SERVERCLOSE

36

服务器关闭

5.3.2 协议实现

协议的指定主要是考虑在进行通信的过程中,保证服务器和客户端的通信消息能够被双方正确的理解,并作出相应的处理,比如登陆失败消息,登陆成功消息,文件传输消息,聊天消息等,服务器和客户端必须要按照指定的规则去打包和解析消息。其中协议的设计是通过对Socket流进行自定义的封装,把已经定义好的对象的每一个属性按照unicode编码中的一些特殊的编码\u0000(空格)进行分隔封装,并发送输入和输出流,另一端安装封装的逆序把输出流封装为对象,并识别该对象随对应是什么样的消息,客户端或者服务器作出相应的处理。而通过继承输入输出流实现了服务器器信息的发送,但是具体的包类型是什么样的消息是通过标示来标记。通过标示来解析这些包是什么样类型的包,实现服务器和客户端之间可理解的通信。其核心类PackOper类主要代码如下:

/**
* 解包类
* @author Administrator
*/
public class PackOper implements PackInterface {/**
* 创建一个包,根据object类型
* @param object
* @return
*/
public byte[] createPackage(Object object) {
if (object == null) {
return null;
}
if (object instanceof MessagePack) {
return createMessagePack((MessagePack) object);
}
if (object instanceof User) {
return createUser((User) object);
}
if (object instanceof Department) {
return createDepartment((Department) object);
}
if (object instanceof Company) {
return createCompany((Company) object);
}
return null;
}
/**
* 创建消息包
* @param pack
* @return
*/
private byte[] createMessagePack(MessagePack pack) {
return createByte(STARTSEPARATOR + pack.getType() + SEAS
+ pack.getFrom() + SEAS + pack.getFromIP() + SEAS
+ pack.getFromPort() + SEAS + pack.getTo() + SEAS
+ pack.getMessage() + ENDSEPARATOR);
}
/**
* 解一般消息包
* @param strs
* @return
*/
private Message unbindMessagePack(String[] strs) {
MessagePack messagePack = null;
if (strs != null) {
try {
messagePack = new MessagePack();
messagePack.setType(strs[0]);
messagePack.setFrom(strs[1]);
messagePack.setFromIP(strs[2]);
messagePack.setFromPort(Integer.parseInt(strs[3]));
messagePack.setTo(strs[4]);
messagePack.setMessage(strs[5]);
} catch (Exception e) {
return null;
}
}
return
}
}

MyObjectInputStream.java,该文件继承输出流,并自定义解析输出流的规则。Unit包里封装了所有消息类封装Bean。MyObjectInputStream.java,该文件继承输入流,并自定义解析输入流的规则。PackOper.java该文件主要实现了,Socket发送字节流的解包规则,并转化字节流为对象。也即服务器实现客户端不同消息识别,服务器端并作出相应处理。

5.4客户端功能模块的设计与实现

5.4.1 登陆认证模块

该模块主要实现用户的登陆认证,以及服务器代理IP和端口的设置,并检查数据的合法性。主要是参考现在通用即时聊天工具QQ界面进行设计,没有采用具体的算法实现漂亮的算法,只是截取QQ界面的图片作为自己设计界面的背景。同时用户登录身份认证使用简单模拟的QQ协议通过发送登陆验证包消息给服务器,服务器解包之后查询数据库检查用户身份的合法性,并发送给客户端认证成功或者失败包,客户端解包之后如果认证成功则登陆成功,显示主界面,否则提示用户登陆失败,提示用户重新登陆。并且可以根据服务器IP和端口的变化进行动态设置服务器地址,具有很好的灵活性。具体实现效果如下图5.6所示。

java 框架 聊天系统 基于java的聊天系统_Java_12

图5.6 用户登陆界面

5.4.2 主界面模块

该模块是参考QQ设计,截取QQ图片作为自己界面设计背景素材。其中分组信息也是通过向服务器发送查询该客户端用户的分组以及好友信息包,服务器解包之后查询数据库,并将查询结果封装成对象之后,转化为Socket流发送给客户端,客户端将包信息解析封装为对象,并显示数据库到客户端主界面上。该模块设计难点主要在如何有效的使用Swing提供的现有组建去扩展,实现漂亮的交互界面。如图5.7:

java 框架 聊天系统 基于java的聊天系统_服务器_13

图5.7 用户登陆后主界面

5.4.3 聊天模块

聊天模块设计思路如下:

该模块是现在比较流行的QQ作为参考,设计的聊天的界面,特别是表情的发送,表情的窗口是FaceUI类封装的,它调用相应的辅助类来实现模拟QQ表情的实现,同时,自定义封装了聊天文本框,来实现文字和图片混合的文本框,在发送的时候获取用户发送的内容,自己封装为预定义好的对象,并转化为Socket流发送,经过服务器,有服务器找到对应客户端并转发消息,另一个客户端运行专门的客户端线程检测消息,接收到服务器的消息之后,自动弹出聊天窗体,并把好友发过来的消息显示在聊天界面上。其中,ChatUI类封装了聊天主界面,实现聊天的功能。FaceUI类实现聊天的时候可以添加表情。其实现效果如下图5.8:

java 框架 聊天系统 基于java的聊天系统_服务器_14

图5.8聊天界面

5.4.4 文件传输模块

该模块主要实现了用户之间的聊天功能,可以传输表情和文字。而且也可以实现不同用户之间多线程的文件传输功能,可以在聊天的同时不影响文件传输并行进行,而且多线程传输文件也提高了文件的传输速度。实现技术组要采用多线程文件传输模块设计,主要实现不同用户之间进行发送文件,SendStreamThread类,该类主要采用多线程的思想,发送Socket流,实现客户端和服务器的通信,并通过服务器实现客户端与另一个客户端通信的功能。ReceiveStreamThread类,该类主要采用多线程的思想,接收Socket流,实现客户端和服务器的通信,接收Socket流并根据QQ协议规则将Socket流转化为相应的消息对象,并通知本地主线程,作出相应的处理。该类无论是在服务器或者是客户端都在一直运行,只要发现有Socket流到来就接收,并交给主线程进行处理。其核心代码如下,以ReceiveStreamThread类为例。

public class ReceiveStreamThread extends Thread {
private Socket socket;
private TransTask transTask;
public ReceiveStreamThread(Socket socket) {
this.socket = socket;
}
public void run() {
BufferedInputStream bufInStream = null;
BufferedOutputStream bufOutStream = null;
MyObjectInputStream myObjectIn = null;
MyObjectOutputStream myObjectOut = null;
try {
myObjectIn = new MyObjectInputStream(socket.getInputStream());
myObjectOut = new MyObjectOutputStream(socket.getOutputStream());
MessagePack msgPack = (MessagePack) myObjectIn.readMessage();
if (!msgPack.getType().equals(PackOper.UPFILE)) {
socket.close();
return;
}
// 寻找是否有此任务
this.transTask = TransFileStock.getReceiveFileUI(msgPack.getMessage());
if (transTask == null) {
socket.close();
return;
}
msgPack.setType(PackOper.UPFILE_FIAT);
myObjectOut.writeMessage(msgPack);
bufInStream = new BufferedInputStream(socket.getInputStream());
bufOutStream = new BufferedOutputStream(new FileOutputStream(
transTask.getSendFile()));
byte[] bufByte = new byte[1024];
int readLen = -1;
int readSum = 0;
while ((readLen = bufInStream.read(bufByte, 0, bufByte.length)) > 0
&& !transTask.getFileUI().isCancel()) {
bufOutStream.write(bufByte, 0, readLen);
readSum += readLen;
transTask.getFileUI().setPlan(readSum);
}
bufOutStream.flush();
if(readSum < transTask.getFileLength()){
transTask.getFileUI().setClose();
}else{
//传送完毕
transTask.getFileUI().setTransFinish();
}
TransFileStock.removeReceiveTrans(transTask.toString());
} catch (UnsupportedEncodingException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
} }
}

其实现效果如下图5.9所示。

java 框架 聊天系统 基于java的聊天系统_服务器_15