2024年4月11日发(作者:)
仿QQ聊天系统的数据库设计与实现
假如你要构建《即时通讯系统》
阅读第4部分 设计你的即时通讯系统中类的关系和数据库
20140522
1 引言
数据库课程设计是指对于一个给定的应用环境,构造设计优化的数据库逻辑模
式和物理结构,并据此建立数据库及其应用系统,使之能够有效地存储和管理数据,满足
用户的应用需求。信息管理要求是指在数据库中应该存储和管理哪些数据对象;数据操作
要求是指对数据对象要进行哪些操作,如查询、加入、删除、修改、统计等操作。数据库
课程设计的目标是为了用户和各种应用系统提供一个信息基础设施和高效率的运行环境。
高效率的运行环境包括:数据库的存取效率、数据库存储空间的利用率、数据库系统运行
管理的效率都是高的。本次课程设计的目的是把所学的数据库的知识应用到实践中去。现
今知识已越来越受到人们的重视,仿QQ聊天系统是参考腾讯公司发布的腾讯QQ,主要运
用数据库知识和C#将其初步实现
[1]
。
1.1课题背景
现在的信息越来越发达,很多人都在使用QQ作为聊天工具,现根据腾讯公司的QQ
聊天系统制造属于自己的聊天工具,表面上看上去是仿QQ聊天系统,其实等到时机成熟
可以换成别的名字,相信在不远的将来在老师和同学们的帮助下,再借助互联网,我们一
定可以打造出属于自己的聊天系统。当然系统存在着很多不足,需要老师的指点和帮助。
1.2系统需求分析
QQ聊天系统是大家广泛喜欢经常应用到CS应用程序软件[2],而现在仿QQ聊天系统
开发工具,是本人对其程序的深感兴趣,不但可以了解从中的业务,而且还可以加强学习,
以及对知识的回顾。同时也是尽快测试此聊天程序,以便和同学进行用自己的工具来交流
聊天,由于好奇心促使和同学们一起来探讨此程序的开发,这样增强同学们之间的相互交
流,相互学习。
该系统属于应用程序,需要对数据的处理,比如聊天信息要既是反馈给对方,故对数据的
及时更新要求较高,保证数据的真实性.该系统在任何操作系统下都可以运行,但必须装有
SQL2000数据库。
2 关键技术简介
2.1 SQL Server2000
SQL Server 2000 是Microsoft 公司2000年推出的SQL Server 数据库管理系统的版本。
它是一个杰出的数据库平台,可用于大型联机事务处理、数据仓库、以及电子商务等。特
点: 真正的客户机/服务器体系结构, 图形化用户界面, 丰富的编程接口工具。 SQL Server
与Windows NT完全集成, 具有很好的伸缩性,支持Web技术。 SQL Server提供数据仓库功
能
[3]
。
2.2 C#简介
C#是从C和C++派生来的一种简单、现代、面向对象和类型安全的编程语言。C#是用
于创建运行在.NET公共语言运行库上的应用程序的语言之一,它从C语言和C++语言演化
而来,是Microsoft专门使用.NET平台而创建的,并且考虑了其他语言的许多有点。
由于语法简单,使用C#开发应用程序比C++程序相对简单。但是,C#也是一种强大的
语言,在C++中能完成的任务在C#中同样也能完成。C#的代码要比C++略长些,这是因为
C#是一种类型安全的语言(与C++不同),虽然C#的代码略长但其代码更健壮,调试也比
较简单。
C#是唯一为.NET Framework而设计的语言,是移植到其他操作系统上的.NET版本中使
用的主要语言,能使用.NET Framework代码库提供的每种功能。反之,如果要使用
等语言尽可能与其以前的语言类似,而且仍然遵循CLR,这些语言就不能完全支持.NET代
码库的某些功能。C#可以创建Windows应用程序,Web应用程序,Web服务这几种常见
的应用程序
[4]
。具体实现如下:
1:首先根据对其业务逻辑的分析极其全面整合,加之我们所熟悉的QQ聊天技术。第
一应该做的是界面,界面的美化程度直接反映着用户对此软件喜欢程度,所以借助了互联
网搜索了一些好看的图片;
2:对界面的设计,这里所用到的就是C#里布局控件,精心的布局,这一点众所周之
C#里丰富的控件为我们提供了方便,这样做就可以尽可能的让用户用起来比较舒服;
3:各个窗体画好后,接下来自然就是业务逻辑层的代码书写了,由于学习不够精,
所以在书写代码方便并没有用到三层技术,但是本人对该系统考虑的比较全面,一些错误
和异常都可以将其打印出来
书写代码比较规范,不管从类的书写,还是一些命名都非常规范;
C#里提供丰富的控件库,本来就可以自动生成一些代码,对业务逻辑比较明朗,对方
法和类之间的命名比较规范,书写代码自然比较快,出错率比较少;方法就是增删改查,
最后结合数据库技术完成业务逻辑。
3 数据库概念结构设计
3.1 构思E-R图原则
原则1:能独立存在的事物,例如人、物、事、活动、事项等等,在其有多个基本项
描述的特性需要关注时,就应把它作为实体。
根据原则1,分析本系统中的实体主要有用户、星座、信息类型、聊天信息、好友策
略、好友和血型。
原则2:两个或多个实体间的关联与结合,如主管、从属、组成、占有、作用、配合、
协同等等,当需要予以关注时,应作为联系。联系通常是某类行为动作,E-R图关注的是
其状态与结果而非其过程。
根据原则2,对本系统间的实体之间的关联进行分析,用户与星座、血型、好友策略之间
有组成与被组成的关系;在这里解释一下所谓的好友策略,我们在聊天时,别人可能会加我们
为好友,我们可以不通过系统的提示,自动允许,这是一种策略。另外一种策略就是别人要加
我们为好友时,先通过系统信息请求我们是否同意。此外,QQ消息和消息类型之间也有组成
与被组成的关系。
原则3:实体的属性是实体的本质特征。实体应有标识属性,并指定其中一个作为主
标识。联系的属性是联系的结果或状态。属性具有如下几个特点:非多值性、非复合性、
非导出性。实体的属性还应有非关联性。
根据原则3,分析本系统中的实体属性。QQ用户的属性包括QQ号(标识属性)、QQ密
码、用户昵称、用户真实姓名、性别和年龄等;星座的属性包括星座的编号(标识属性)和名
称;血型的属性包括血型编号(标识属性)和名称;好友策略的属性包括策略编号(标识属性)和
策略名称;消息类型包括消息类型编号(标识属性)和消息类型名称;QQ消息的属性包括消息
记录编号(标识属性)、消息记录名称、消息接受状态和接发消息的时间
原则4:所有基本项在同一E-R图中作为属性要在仅在一个地方出现
[5]
。
3.2设计E-R图
根据构思E-R图的原则联系本系统的需求分析,将数据库中所涉及的各个实体与
它们各自的属性以及各个实体之间的关联用E-R图的形式表现出来,实体用方形表示,属
性用椭圆表示,关联关系用没有箭头的直线连接,具体如下图3.1所示:
消息
消息记录编号
消息接受状态
消息类型名称
QQ消息
发消息时间
1
1
组成
好友记录编号
N
消息类型
好友记录
1
消息类型编号
包括
组成
N
收发消息者
N
两两好友
QQ号
QQ密码
年龄
昵称
用户
M
组成
组成
N
N
血型编号血型
血型名称
N
好友策略
头像
好友策略编号
好友策略名称
组成
M
M
组成
N星座
星座名称
性别
星座编号
真实姓名
M
头像编号
头像图片
图3.1 QQ系统E-R图
3.3 E-R图向关系模型转换原则
(1)
一个1:1联系可以转换为一个独立的关系模式,也可以与任意一端对应的关
系模式合并。如果转换为一个独立的关系模式,则与该联系相连的各实体的码以及联系本
身的属性均转换为关系的属性,每个实体的码均是关系的候选码。如果与某一端实体对应
的关系模式合并,则需要在改关系模式的属性中加入另一个关系模式的码和联系本身的属
性。
(2)一个1:n联系可以转换为一个独立的关系模式,也可以与n端对应的关系模式合
并。如果转换为一个独立的关系模式,则与该联系相连的各实体的码以及联系本身的属性
均转换为关系的属性,而关系的码为n端实体的码。
(3)一个m:n联系转换为一个关系模式。与该联系相连的各实体的码以及联系本身
的属性均转换为关系的属性,各实体的码组成关系的码或关系码的一部分。
(4)3个或3个以上实体间的一个多元联系可以转换为一个关系模式。与该联系相连
的各实体的码以及联系本身的属性均转换为关系的属性,各实体的码组成关系的码或关系
码的一部分。
(5)具有相同码的关系模式可合并
[6]
。
根据这5项实体间的联系将上述E-R图转换为关系模型
QQ消息(消息记录编号、消息、消息接受状态、发消息时间)
此为消息实体对应的关系模式,该关系模式已包含了联系“组成”所对应的关系模式。
消息类型(消息类型编号、消息类型名称)
此为消息类型实体对应的关系模式,该关系模式已包含了联系“组成”所对应的关系
模式。
用户(QQ号、QQ密码、昵称、真实姓名、年龄、性别)
此为用户实体对应的关系模式,该关系模式已包含了联系“组成”所对应的关系模式。
星座(星座编号、星座名称)
此为星座实体对应的关系模式,该关系模式已包含了联系“组成”所对应的关系模式。
血型(血型编号、血型名称)
此为血型实体对应的关系模式,该关系模式已包含了联系“组成”所对应的关系模式。
好友策略(好友策略编号、好友策略名称)
此为好友策略实体对应的关系模式,该关系模式已包含了联系“组成”所对应的关系
模式。
数据库逻辑结构设计
4.1 数据库需求分析
针对自己所要设计的仿QQ聊天系统的需求,设计如下所示的数据项和数据结构:
用户表:QQ号码、QQ密码、加好友的方式编号、昵称、QQ头像编号、性别、年龄、
实姓名、星座编号、血型编号
星座表:星座编号、星座名称
信息类型表:信息类型编号、信息类型
聊天信息表:聊天信息表记录编号、发送信息者QQ号、收到信息者QQ号、发送信
息、信息类型编号、信息状态、发送时间
好友策略表:加好友的方式编号、加好友的方式设置
好友表:表添加记录、发送者的QQ、好友的QQ
血型表:血型编号、血型 以上内容如图4.1所示:
用户登录
信息填写正确
操作
用户命令
登录失败
注册
主窗体
操作
查找
好友列表
显示所有QQ
执行命令
操作
选中
加为好友
删好朋,修改头像
聊天
图4.1 数据流图
根据本系统的业务逻辑关系,得出了此数据流图,每一个箭头都带表着数据的流向,
而数据的流向直接反映给数据库,并将此信息保存在数据库,从而比较正确的设计出数
据库。
4.2 数据库初步关系框架
User(用户表)( QQ号码、QQ密码、加好友的方式编号、昵称、QQ头像编号、性别、
年龄、真实姓名、星座编号、血型编号)
Star(星座表)(星座编号、星座名称)
MessageType(信息类型表)( 信息类型编号、信息类型)
Messages(聊天信息表)( 聊天信息表记录编号、发送信息者QQ号、收到信息者QQ号、
发送信息、信息类型编号、信息状态、发送时间)
FriendshipPolicy(好友策略表)( 加好友的方式编号、加好友的方式设置)
Friends(好友表)( 表添加记录、发送者的QQ、好友的QQ)
BloodType(血型表)( 血型编号、血型)
4.3数据库关系模式优化
该系统的数据库设计是满足数据库设计的第三范式。在设计数据库的时候例如对本数
据库中任意一个表,例如用户表;
在关系模式R中的每一个具体关系r中,如果每个属性值 都是不可再分的最小数据单
位,则称R是第一范式的关系。例如QQ号码,用户昵称,用户真实姓名,年龄(一个人
可能只有一个用户昵称,一个QQ号码,用户的编号,一个姓名,电话号码……)
如果一是重复存储用户的QQ号码和姓名。这样,关键字只能是用户的编号。
很显然这种方法是不可取的;
如果用户的QQ号码是关键字,电话号码分为单位电话和住宅电话两个属性。
所以说:用户表中的列是不可再分的(即列的原子性),则可以说明该表满足第一范
式!
如果关系模式R(U,F)中的所有非主属性都完全依赖于任意一个候选关键字,则称
关系R 是属于第二范式的。
还拿出上面所说的用户表,例如每个用户都自己的详细信息(即,例如qq的头像编
号,血型,星座……)
那么我们可以简单的举几个例子就可以很简单的看出;
a. 数据冗余,假设同一种血型由50个学生都一样,那么血型就重复了50次。
b. 更新异常,若调整了某种血型,相应的元组血型值都要更新,有可能会出现血
型的不同。
c. .插入异常,如果科学家研究出来一种新的血型,由于没人选修,没有qq号作
为关键字,只能等有人选修才能申请qq和录入血型成功。
d. 删除异常,如果qq管理员要删除过期的qq或者是很久没有人用的qq,从当
前数据库删除选修记录。那么刚要申请qq号的人,则申请的qq号和个人的血型都无
法保存。
原因是:血型都要依赖于血型的编号。
解决方法:分成两个关系模式分别在用户表血型编号,和血型表中的血型编号建立关
系,即需要时再进行自然联接,恢复了原来的关系
[7]
。
所以说综合上面所叙述,此数据库满足第二范式。
如果关系模式R(U,F)中的所有非主属性对任何候选关键字都不存在传递信赖,则
称关系R是属于第三范式的。
仍然按照上面的例子来说明,即例如每个用户都自己的详细信息(即,例如qq的头
像编号,血型,星座……)
如果只按照qq作为关键字,没有部分依赖的问题,肯定是2NF。但这关系肯定有大量
的冗余,有关用户属性将重复存储,插入,删除和修改时也将产生类似以上例的情况。
原因:关系中存在传递依赖造成的。假如要插入星座中的白马座,显然它不属于12
星座,这样插入很显然是不会成功的,关键是用户星座的编号和星座表中的编号相互联系
起来的,也就是函数决定是通过传递依赖。
解决目地:每个关系模式中不能留有传递依赖。
这样就满足了第三范式!
这样做的目的就是:规范化目的是使结构更合理,消除存储异常,使数据冗余尽量小,
便于插入、删除和更新
原则:遵从概念单一化 "一事一地"原则,即一个关系模式描述一个实体或实体间的一
种联系。规范的实质就是概念的单一化
[8]
。就是增加系统的稳定性以及系统的成本和后期
的维护。
方法:将关系模式投影分解成两个或两个以上的关系模式。
要求:分解后的关系模式集合应当与原关系模式"等价",即经过自然联接可以恢复原
关系而不丢失信息,并保持属性间合理的联系。
从而在建立数据逻辑时能够更加清晰明白避免数据的冗杂,降低了出错的可能性使得
该系统更加可靠。
通过上面的数据库关系优化之后我们就可以很简单的写出逻辑关系。
4.4 具体逻辑模式设计
表4.1 用户表Users
字段
Id
LoginPwd
FriendshipPolicyId
NickName
FaceId
Sex
Age
Name
StarId
BloodTypeId
表4.2 星座表Star
字段
Id
Star
表4.3信息类型表MessageType
字段
Id
字段类型
int
字段描述
信息类型编号(主
键)
字段类型
int
varchar
int
号
varchar
int
varchar
int
varchar
int
int
字段描述
QQ号码(主键)
QQ密码
加为好友的方式编
昵称
QQ头像的编号
性别
年龄
真实姓名
星座编号
血型编号
字段类型
int
varchar
字段描述
星座编号(主键)
星座名称
MessageType
varchar
信息的类型
表4.4聊天信息表Messages
字段
Id
FromUserId
字段类型
int
int
字段描述
聊天信息表记录编
号(主键)
发送信息者QQ号
(外键)
int
varchar
int
int
datetime
续表4.4
收到信息者的QQ号
(外键)
Message
MessageTypeId
MessageState
MessageTime
表4.5好友策略表FriendshipPolicy
字段
Id
FriendshipPolicy
表4.6好友表Friends
字段
Id
HostId
FriendId
表4.7血型表BloodType
字段
Id
BloodType
ToUserId
发送的信息
信息的类型编号
信息的状态(被接收
到为1)
发送的时间
字段类型
int
varchar
字段描述
加为好友的方式编
号(主键)
加为好友的方式的
设置
字段类型
int
int
int
字段描述
好友表表添加的记
录(主键)
发送者的QQ(外键)
好友的QQ(外键)
字段类型
int
varchar
字段描述
血型编号(主键)
血型
4.5 数据库设计表
在上述每张表中,第一个数据都作为自己所在表的主键,而在表与表之间也有主外键
关系存在,对用户表和星座表来说,星座表是主键表,用户表是外键表;对用户表和血型
表来说,血型表是主键表,用户表是外键表;对用户表和好友策略表来说,好友策略表是
主键表,用户表是外键表;对聊天信息表和信息类型表来说,信息类型表是主键表,聊天
信息表是外键表。
表4.8 设计表Users
表4.9 设计表BloodType
表4.10 设计表Friends
表4.11 设计表FriendshipPolicy
表4.12 设计表Messages
表4.13 设计表MessageType
表4.4 设计表Star
4.6 关系图
图4.2 关系图
5 程序实现
5.1界面和系统设计
该界面用户可以申请号码,然后注册自己的基本信息,若注册成功就可得到一个
QQ号码,并根据此号码加上自己在注册基本资料时注册的密码就可以实现用户的登录,
具体操作见下列各图5.1到图5.14所示:
图5.1 用户登录运行界面
具体实现:在Visual 2005的Windows应用程序里面,首先创建一个名为
“MyQQ用户登录”的主窗体,然后按照需要的功能拖控件,
如果用户名和密码为空:
图5.2 登录提示界面 1
("请输入登录的号码", "登录提示",
,
ation);
();
如果密码有错:
则由图5.3所示:
图5.3 登录提示界面 2
具体实现代码如下:
("请输入密码", "登录提示",
,
ation);
如果用户名和密码都对:
return false;
}
return true;
}
图5.4 申请号码的运行界面
创建“申请号码”主窗体,此窗体由三部分组成,具体操作同上,部分涉及数据库信
息的代码如下:
// 查询星座用的sql语句
string sql = "SELECT Star FROM Star";
// 修改查询语句,查询血型
sql = "SELECT BloodType FROM BloodType";
bloodTypeId = GetBloodType();
// 获得血型的Id
sql = ("INSERT INTO Users (LoginPwd, NickName, Sex, Age,
Name, StarId, BloodTypeId) values ('{0}','{1}','{2}',{3},'{4}',{5},{6})",
(), (), sex,
(()), (), starId, bloodTypeId); // 获得星座的Id
starId = GetStarId();
sql = ("INSERT INTO Users (LoginPwd, NickName, Sex, Age,
Name, StarId) values ('{0}','{1}','{2}',{3},'{4}', {5})",
(), (), sex,
(()), (),starId);
图5.5 登录后运行界面
此界面具体功能未能实现。
5.2界面具体操作
打开用户登录,申请号码注册:
图5.6 用户登录
点击申请号码以后,注册自己的基本信息,包括昵称、年龄、性别、密码、真实姓名、
星座和血型。
图5.7 用户注册界面
注册成功后,将获得提示。
如图5.8所示:
图5.8 注册成功提示
注册成功以后,用申请的号码和自己的密码进行登录。
如图5.9所示:
图5.9 用户登录界面
如果用户名和密码有错则会:
如图5.10所示:
图5.10 用户登录出错
具体实现代码如下:
("请输入密码", "登录提示",
,
ation);
如果用户名和密码都对:
return false;
}
return true;
}
其效果图如图5.11所示:
图5.11 用户登录成功后的主窗体
好友列表——第三方控件运用了第三方SideBar
// 命名空间
using ;
// 添加组
up("我的好友");
up("陌生人");
// 添加项
SbItem item = new SbItem((string)dataReader["NickName"],
[0].(item);
如果要添加好友的话:
将通过三步来实现。
a. 查找 如图5.12所示
b. 添加 如图5.13所示
c. 反馈成功信息 如图5.14所示
图5.12 查找好友
图5.13 好友列表
图5.14 加载好友已经存在
// 添加好友
private void btnAdd_Click(object sender, EventArgs e)
{
int friendshipPolicyId = -1;
// 对方的好友策略
int friendId = GetSelectedFriendId();
// 获得选中的好友的Id
// 是否有可添加的好友
if (friendId == -1)
("请选择一个好友!", "提示",
{
, ation);
return;
}
else if (friendId == d)
{
("不能加自己为好友!", "提示",
, ation);
return;
}
else if (HasAdded(friendId))
// 确认是否需要添加(是否已经是好友了)
{
("对方已在你的好友列表中!", "提示",
, ation);
return;
}
// 确认对方能否被加为好友
if (friendshipPolicyId == 3)
// 3表示不允许任何人添加,在S2可以使用常
friendshipPolicyId = GetFriendshipPolicyId(friendId);
量或枚举
{
("对方不允许任何人加他为好友!", "提示",
, ation);
return;
}
else if (friendshipPolicyId == 2) // 2:表示需要身份验证
{
int result = SendRequest(friendId);
// 发验证消息
if (result == 1)
{
("对方需要身份验证才能被加为好友,已发出请求!
", "提示",
, ation);
}
else
{
("添加失败,请稍候再试!", "提示",
, g);
}
}
else if (friendshipPolicyId == 1)
// 1:表示允许任何人添加为好友
{
// 执行添加操作
int result = AddFriend(friendId);
if (result == 1)
{
("添加成功,请刷新好友列表!", "提示",
, ation);
}
else
{
("添加失败,请稍候再试!", "提示",
, g);
}
}
}
结 束 语
因个人能力有限,本课程设计的仿QQ聊天系统是一个不完善的系统,通过这次的锻炼,
让我深刻的意识到计算机科技的广泛性。同时,作为计算机专业的一名学生,把专业课学
好学精是我以后的学习目标。运用计算机知识来帮助社会解决难题也是我以后人生奋斗的
目标。因为这次是数据库的课程设计,所以重点还是体现在数据库的设计方面。同时也因
个人能力有限,想做出更多的功能却实现不了,个人能力有待于提高。
参考文献
[1] 面向对象的程序设计语言[M] 陈志泊,王春玲.人民邮电出版社2002
[2] /question/?si=3
[3] 数据库系统概论[M] 王珊,萨师煊. 2006 高等教育出版社2006
[4] C#程序设计[M] 李乃文,傅游,沈学利 任建华. 清华大学出版社2007
[5] 数据库系统概论[M] 王珊,萨师煊.高等教育出版社2006
[6] 数据库系统概论[M] 王珊,萨师煊. 高等教育出版社2006
[7] 管理信息系统的发展方向及实现技术[M] 张巨俭,甘仞初.计算机应用研究,机械
工业出版社2003
[8] 中文版 SQL Server 2000 开发与管理应用实例[M] 邹建人民邮电出版社 2008
致 谢
在这次数据库的课程设计中,因自己能力的问题曾遇到过不少问题,单靠我个人的努
力,很难按时完成该课程设计。另外,还要感谢老师的指导和各位同学对我们的关怀、帮
助,为我们提供了良好的设计环境以及各方面的支持。
另外,还要感谢个别同学对我的帮助和鼓励,是我对数据库有了更深一步的理解,锻
炼了自己。
附录:部分源代码
("请输入登录的号码", "登录提示", ,
ation);
();
如果密码有错:
具体实现代码如下:
("请输入密码", "登录提示", ,
ation);
如果用户名和密码都对:
return false;
}
return true;
}
创建“申请号码”主窗体,此窗体由三部分组成,具体操作同上,部分涉及数据库信
息的代码如下:
// 查询星座用的sql语句
string sql = "SELECT Star FROM Star";
// 修改查询语句,查询血型
sql = "SELECT BloodType FROM BloodType";
// 获得血型的Id
bloodTypeId = GetBloodType();
sql = ("INSERT INTO Users (LoginPwd, NickName, Sex, Age,
Name, StarId, BloodTypeId) values ('{0}','{1}','{2}',{3},'{4}',{5},{6})",
(), (), sex,
(()), (), starId, bloodTypeId);
// 获得星座的Id
starId = GetStarId();
sql = ("INSERT INTO Users (LoginPwd, NickName, Sex, Age,
Name, StarId) values ('{0}','{1}','{2}',{3},'{4}', {5})",
(), (), sex,
(()), (),starId);
// 添加好友
private void btnAdd_Click(object sender, EventArgs e)
{
int friendshipPolicyId = -1; // 对方的好友策略
int friendId = GetSelectedFriendId(); // 获得选中的好友的Id
// 是否有可添加的好友
if (friendId == -1)
{
("请选择一个好友!", "提示",
, ation);
return;
}
else if (friendId == d)
{
("不能加自己为好友!", "提示",
, ation);
return;
}
else if (HasAdded(friendId)) // 确认是否需要添加(是否已经是好友了)
{
("对方已在你的好友列表中!", "提示",
, ation);
return;
}
// 确认对方能否被加为好友
friendshipPolicyId = GetFriendshipPolicyId(friendId);
if (friendshipPolicyId == 3) // 3表示不允许任何人添加,在S2可以使用常
量或枚举
{
("对方不允许任何人加他为好友!", "提示",
, ation);
return;
}
else if (friendshipPolicyId == 2) // 2:表示需要身份验证
{
int result = SendRequest(friendId); // 发验证消息
if (result == 1)
{
("对方需要身份验证才能被加为好友,已发出
请求!", "提示", , ation);
}
else
{
("添加失败,请稍候再试!", "提示",
, g);
}
}
else if (friendshipPolicyId == 1) // 1:表示允许任何人添加为好友
{
// 执行添加操作
int result = AddFriend(friendId);
if (result == 1)
{
("添加成功,请刷新好友列表!", "提示",
, ation);
}
else
{
("添加失败,请稍候再试!", "提示",
, g);
}
}
}
import edReader;
import edWriter;
import treamReader;
import StreamWriter;
import riter;
import Socket;
import ;
public class MutiChat
{
public static void main(String[] args)
{
MutiChat mc = new MutiChat();
e().start();
().start();
}
/**
* 接收信息
*
* @return
*/
private Thread receive()
{
return new Thread()
{
public void run()
{
ServerSocket server_socket = null;
Socket sk = null;
BufferedReader in = null;
try
{
server_socket = new ServerSocket(7777);
sk = server_();
in = new BufferedReader(new InputStreamReader(sk
.getInputStream()));
while (true)
{
String str = ne();
n(str);
}
} catch (Exception e)
{
tackTrace();
}
}
};
}
private Thread send()
{
return new Thread()
{
public void run()
{
Socket client_socket = null;
BufferedReader in = null;
PrintWriter out = null;
while (true)
{
try
{
client_socket = new Socket("127.0.0.1", 8888);
};
}
}
in = new BufferedReader(
new InputStreamReader());
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(client_socket
.getOutputStream())), true);
while (true)
{
String str = ne();
n(str);
}
} catch (Exception e)
{
try
{
(1000);
} catch (Exception ex)
{
tackTrace();
}
}
}
}
import edReader;
import edWriter;
import treamReader;
import StreamWriter;
import riter;
import Socket;
import ;
public class MutiChat2
{
public static void main(String[] args)
{
MutiChat2 mc = new MutiChat2();
e().start();
().start();
}
/**
* 接收信息
*
* @return
*/
private Thread receive()
{
return new Thread()
{
public void run()
{
ServerSocket server_socket = null;
Socket sk = null;
BufferedReader in = null;
try
{
server_socket = new ServerSocket(8888);
sk = server_();
in = new BufferedReader(new InputStreamReader(sk
.getInputStream()));
while (true)
{
String str = ne();
n(str);
}
} catch (Exception e)
{
tackTrace();
}
}
};
}
private Thread send()
{
return new Thread()
{
public void run()
{
Socket client_socket = null;
BufferedReader in = null;
PrintWriter out = null;
while (true)
{
try
{
client_socket = new Socket("127.0.0.1", 7777);
in = new BufferedReader(
new InputStreamReader());
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(client_socket
.getOutputStream())), true);
while (true)
{
String str = ne();
n(str);
}
} catch (Exception e)
{
try
{
(1000);
} catch (Exception ex)
{
tackTrace();
}
}
}
}
};
}
}
下面这个是可以带图形界面的
Server:
package ChatIV;
import .*;
import .*;
import .*;
//广播聊天室服务端
public class Server {
public static void main(String args[]){
try {
ServerSocket ss = new ServerSocket(8186);//实现Socket
List sockets = new ArrayList();//创建一个集合,保存文字消息
while(true){
Socket s = ();//监听8186
(s);//向集合中添加Socket的对象S,把听到的内容保存
到集合中
Thread t1 = new ChatThread(s,sockets);//线程
();
}
} catch (IOException e) {
tackTrace();
}
}
}
class ChatThread extends Thread{
Socket s;
List sockets;
public ChatThread(Socket s,List sockets){
this.s=s;
s=sockets;
}
public void run(){
try {
BufferedReader in = new BufferedReader(
new InputStreamReader(utStream()));//包装成字符流
while(true){
String str = ne();//读BufferedReader
for(int i=0;i<();i++){//利用For循环遍历集合
Socket s2 = (Socket)(i);//创建Socket对象S2,强转成
Socket,并获取下标
PrintWriter out = new PrintWriter(putStream());//文本
流输出
n(str);//打印字符
();//刷新该流的缓冲
}
}
} catch (IOException e) {}
finally{
try {
();
} catch (IOException e) {}
}
}
}
Client:
package ChatIV;
import Event;
import Listener;
import edReader;
import ption;
import treamReader;
import riter;
import ;
import nHostException;
import ;
import lPane;
import rea;
import ield;
//广播聊天室客户端
public class Client {
JTextArea jta;
JTextField jtf;
BufferedReader in;
PrintWriter out;
//Swing画一个界面
private void initGUI(){
JFrame f=new JFrame("Client");
e(400,300);
aultCloseOperation(_ON_CLOSE);
jta=new JTextArea();
table(false);
(new JScrollPane(jta));
jtf=new JTextField();
(jtf,"South");
ible(true);
ionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
String text=t();
t("");
n(text);
();
}
});
}
//连接初始化
private void initNet(){
try {
Socket s = new Socket("127.0.0.1",8186);//创建Socket端口8186,端口号
随意,避免常用端口即可
out = new PrintWriter(putStream());//文本流输出,利用Socket对
象获得getOutputStream()
in = new BufferedReader(new InputStreamReader(utStream()));//包
装成字符流
} catch (UnknownHostException e) {
tackTrace();
} catch (IOException e) {
tackTrace();
}
}
//消息接收
private void receive(){
try {
while(true){
String str = ne();//读BufferedReader
if(str==null){
return ;
}
("说"+str+"n");//加载到JTextArea中,显示
}
} catch (IOException e) {
tackTrace();
}
}
private Client(){
I();
t();
}
public static void main(String args[]){
Client c = new Client();
e();
}
}
发布评论