资源描述
攀枝花学院
Java程序设计课程设计
题 目: 聊天程序
学生姓名: Puter
学 号: 201310803036
所在院(系): 数学与计算机学院
专 业: 网络工程
班 级: 2013级网本
指 导 教 师: 吴建斌 职称: 导师
2014 年 12 月 31 日
攀枝花学院本科学生课程设计任务书
题 目
聊天程序
1、课程设计的目的
通过本课程设计使学生能够较全面的掌握面向对象程序设计的有关概念和开发方法,以便能较全面地理解、掌握和综合运用所学的知识,提高自身的编程能力。
2、课程设计的内容和要求(包括原始数据、技术要求、工作要求等)
该程序实现聊天功能,包括服务器段程序和客户端程序。要求:
(1)客户端程序:可连接到服务器,并将消息发送到服务器端和接受服务器端发送来的消息。
(2)服务器端程序:可将消息发送到客户端和接受客户端发送来的消息。
3、主要参考文献
[1]朱福喜.《Java语言程序设计》(第二版).科学出版社
[2]陈国君等.《Java程序设计基础》(第二版).清华大学出版社
[3] Deitel.《Java大学基础教程》(第六版).电子工业出版社
[4] MaryCampione.《Java语言导学》(第四版).机械工业出版社
[5] Y.Daniel Liang.《Java语言程序设计基础篇》(第六版). 机械工业出版社
[6] Kathy Sierra.《Head First Java》(第二版).东南大学出版社
4、课程设计工作进度计划
序号
时间(天)
内容安排
备注
1
1
分析设计准备
周一
2
2
编程调试阶段
周二至周三
3
1
编写课程设计报告
周四
4
1
考核
周五
总计
5(天)
指导教师(签字)
日期
年 月 日
教研室意见:
年 月 日
学生(签字):
接受任务时间: 年 月 日
注:任务书由指导教师填写。
课程设计(论文)指导教师成绩评定表
题目名称
聊天程序
评分项目
分值
得分
评价内涵
工作
表现
20%
01
学习态度
6
遵守各项纪律,工作刻苦努力,具有良好的科学工作态度。
02
科学实践、调研
7
通过实验、试验、查阅文献、深入生产实践等渠道获取与课程设计有关的材料。
03
课题工作量
7
按期圆满完成规定的任务,工作量饱满。
能力
水平
35%
04
综合运用知识的能力
10
能运用所学知识和技能去发现与解决实际问题,能正确处理实验数据,能对课题进行理论分析,得出有价值的结论。
05
应用文献的能力
5
能独立查阅相关文献和从事其他调研;能提出并较好地论述课题的实施方案;有收集、加工各种信息及获取新知识的能力。
06
设计(实验)能力,方案的设计能力
5
能正确设计实验方案,独立进行装置安装、调试、操作等实验工作,数据正确、可靠;研究思路清晰、完整。
07
计算及计算机应用能力
5
具有较强的数据运算与处理能力;能运用计算机进行资料搜集、加工、处理和辅助设计等。
08
对计算或实验结果的分析能力(综合分析能力、技术经济分析能力)
10
具有较强的数据收集、分析、处理、综合的能力。
成果
质量
45%
09
插图(或图纸)质量、篇幅、设计(论文)规范化程度
5
符合本专业相关规范或规定要求;规范化符合本文件第五条要求。
10
设计说明书(论文)质量
30
综述简练完整,有见解;立论正确,论述充分,结论严谨合理;实验正确,分析处理科学。
11
创新
10
对前人工作有改进或突破,或有独特见解。
成绩
指导教师评语
指导教师签名: 年 月 日
目录
摘要...................................................1
一、 需求分析............................................1
二、 概要设计............................................3
三、 详细设计............................................4四、 调试分析............................................4
五、结论................................................14
六、实验分工.............................................14
七、参考文献..............................................14
22
摘 要
在网络越来越发达的今天,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的聊天工具越来越多,例如,国外的ICQ、国内腾讯公司开发的OICQ。基于Java网络编程的强大功能,本次毕业设计使用Java编写一个聊天系统。
一般来说,聊天工具大多数由客户端程序和服务器程序外加服务器端用于存放客户数据的数据库组成,本系统采用客户机/服务器架构模式通过Java提供的Soket类来连接客户机和服务器并使客户机和服务器之间相互通信,由于聊天是多点对多点的而Java提供的多线程功能用多线程可完成多点对多点的聊天,数据库管理系统用SQL Server2000完成并通过JDBC-ODBC桥访问数据库。 现在的各种聊天工具功能越来越强大,但是它们的唯一的不足就是必须要联网或者下载到它们的服务端,要不然是没法脱离Intenet使用的。为了能在一个没有连接到Intenet的局域网使用聊天工具,那就必须要有服务器端。
本系统就是包括服务器端与客户端,可以在局域网聊天的一个工具。建立在JAVA平台上,系统的设计使用了面向对象技术和面向对象的设计原则。系统采用C/S结构,客户端与客户端以及客户端与服务器端之间通过Socket传送消息。使用JAVA语言编写,开发工具采用Eclipse。服务器端设计与实现过程中,采用了多线程技术,可以在单个程序当中同时运行多个不同的线程,执行不同的任务。大大增强了程序对服务器资源的利用。
聊天系统完成后将可进行多人对多人的聊天,对好友进行添加、删除,对新用户的注册,发送消息、接受消息等等功能。
关键词:多线程 ;客户机/服务器 ;JAVA ; Socket ; Eclipse ; TCP/IP
一、 需求分析
为了更好的掌握java这门课程的内容,同时更好的理解与掌握socket编程,对所有面向对象的编程思想以及编程方法的一个总结、回顾和实践,掌握Java语言编程技巧。要求使用图形用户界面。能实现一个聊天室中多人聊天。可以两人私聊。(提示:使用socket通信)程序描述清晰准确,思路清晰,程序能够实现相应的功能。聊天时系统是通过即时通讯技术来实现在线聊天、交流的软件。目前有2种架构形式,1、一种是C/S架构,采用客户端/服务器形式,用户使用过程中需要下载安装客户端软件,典型的代表有:QQ、百度HI 、Skype QQ VS GU、Gtalk、新浪UC、MSN等;2、采用B/S架构,即浏览器/服务端形式,这种形式的即时通讯软件,直接借助互联网为媒介、客户端无需安装任何软件,既可以体验服务器端进行沟通对话,一般运用在电子商务网站的服务商,典型的代表有Websitelive 、53KF、live800等
二、概要设计
目前国内外做聊天系统的公司很多,产品也琳琅满目,国内有诸如腾讯QQ、新浪UC、网易泡泡等,国外有著名的MSN(新版改名为Live Messenger)以及跨平台Gaim等。本人取最具代表性的QQ和MSN进行了一些研究,作为我开发聊天系统的准备。
腾讯无疑是国内即时通讯市场的霸主,自从99年进入即时通讯领域并迅速占市场之后,其在国内用户数量始终高居榜首,即使近几年面对微软MSN的强大攻势,腾讯QQ的时常占有率依然稳步增长。腾讯的成功与其对QQ的不断创新和完善是分不开的。
参考了许多网络上的资料,以及自己通过观察腾讯QQ运行时的各种细节。可以确定腾讯QQ是以多服务器提供服务、服务器总控客户端、客户端之间UDP直连通信的。并且在两个客户端之间不能建立直连的情况下,才由服务器进行中转通信。
其模型如图1-1
图1.1
三、 详细设计
通过TCP网络编程,主要编写有客户端与服务器端两个部分,服务器端通过循环一直从客户端接收信息,并通过线程实现多个客户端连接。服务器发送信息则通过定义链表保存客户端信息。每个客户端向服务器发送信息时,则通过链表中的所有客户端的连接而发送信息给所有客户端界面从而实现局域网内多人聊天。而客户端则主要是界面的编写,通过一个线程一直从服务器获取信息,如果不为空时就在界面上显示。
四、 调试分析
1、 首先运行服务器如图1.2:
图1.2
分析:服务器进入阻塞状态。等待连接。
主要代码:
package .server;
import java.io.IOException;
import .ServerSocket;
import .Socket;
import java.util.ArrayList;
import java.util.List;
import .server.thread.ThreadServer;
public class Server { //服务器功能实现
private ServerSocket server = null ;
public static List<Socket> list = new ArrayList<Socket>() ;//定义链表储存客户信息
private Socket client = null ;
private int count = 0 ;
public Server(){
try {
server = new ServerSocket(8888) ; //创建服务器
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("等待服务器被连接······");
boolean flag = true ;
while(flag){
synchronized(this){
try {
client = server.accept() ;
count++; //记录客户连接数目
} catch (IOException e1) {
e1.printStackTrace();
}
list.add(client) ;
System.out.println("第"+count+"客户端被连接!");
try {
new Thread(new ThreadServer(client)).start();//定义线程,实现多个客户端连接
} catch (Exception e) {
e.printStackTrace();
flag = false ;
}
}
}
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package .server.thread;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import .Socket;
import java.util.Iterator;
import .server.util.ListCO;
public class ThreadServer implements Runnable{ /定义线程,实现多个客户端连接
private BufferedReader buf = null ;
private Socket client = null ;
public ThreadServer(Socket client) throws Exception{
this.client = client ;
buf=new BufferedReader(new InputStreamReader(this.client.getInputStream())) ; //连接从客户端获取信息
}
@Override
public void run(){ //线程
String str = null ;
boolean f = true ;
while(f){ //一直与连接的客户端通讯
try {
str = buf.readLine() ;
} catch (Exception e) {
f = false ;
}
if("bye".equals(str)){
f = false ;
}else{
ListCO lout = null ;
try {
lout = new ListCO();
} catch (Exception e) {
e.printStackTrace();
}
Iterator<PrintStream> iter = lout.getLout().iterator();//向所有的客户端发送信息
while(iter.hasNext()){
PrintStream o = iter.next() ;
o.println(str);
}
}
}
}
}
package .server.util;
import java.io.PrintStream;
import .Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import .server.Server;
public class ListCO { //保存客户端的连接
private List<Socket> list = null ; //通过链表保存
private List<PrintStream> lout = null ;
public ListCO() throws Exception{
this.list = Server.list ;
lout = new ArrayList<PrintStream>() ;
Iterator<Socket> ilist = list.iterator() ;
while(ilist.hasNext()){
PrintStream out = null ;
Socket c = ilist.next() ;
out = new PrintStream(c.getOutputStream()) ;
lout.add(out) ;
}
}
public List<PrintStream> getLout() {
return lout;
}
public void setLout(List<PrintStream> lout) {
this.lout = lout;
}
}
2、客户端的启动如图1.3、图1.4:
图1.3
分析:登录界面先设置聊天使用的名字
图1.4
分析:启动时先输入聊天姓名,然后才进入聊天,这样就可以进行多人聊天了。
主要代码:
package .client;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintStream;
import .Socket;
public class clientAPP { //客户端界面
private JFrame frame;
private JTextField textField_1;
private JTextField textField_2 = new JTextField() ;
private final JTextArea textArea = new JTextArea() ;
JLabel lblNewLabel = new JLabel();
JButton btnNewButton2 = null ;
private Socket client = null ;
private PrintStream out = null ;
private String name ;
/**
* Launch the application.
*/
public static void main(String[] args) {
clientAPP window = new clientAPP();
window.startAPP();
}
/**
* Create the application.
* @return
*/
public void startAPP() { //登录界面
final JFrame f = new JFrame("聊天帅名") ;
f.getContentPane().setForeground(Color.GREEN);
f.getContentPane().setFont(new Font("新宋体", Font.BOLD, 20));
f.setBounds(700, 320, 450, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(null);
JLabel lblNewLabel2 = new JLabel("\u8BF7 \u8BBE \u7F6E \u4F60 \u9017 \u540D");
lblNewLabel2.setForeground(Color.RED);
lblNewLabel2.setBackground(Color.RED);
lblNewLabel2.setFont(new Font("新宋体", Font.BOLD, 25));
lblNewLabel2.setBounds(108, 23, 226, 50);
f.getContentPane().add(lblNewLabel2);
textField_2.setForeground(Color.CYAN);
textField_2.setFont(new Font("新宋体", Font.BOLD, 22));
textField_2.setBounds(130, 97, 168, 41);
f.getContentPane().add(textField_2);
textField_2.setColumns(10);
btnNewButton2 = new JButton("\u8FDB\u5165");
btnNewButton2.setFont(new Font("微软雅黑", Font.BOLD, 30));
btnNewButton2.setForeground(Color.BLUE);
btnNewButton2.setBounds(145, 165, 127, 41);
f.getContentPane().add(btnNewButton2);
f.setVisible(true);
btnNewButton2.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
frame.setVisible(true); //登录后才显示聊天界面
f.setVisible(false); //隐藏登录界面
lblNewLabel.setText("我叫:"+textField_2.getText());
}
});
}
public clientAPP() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() { //聊天界面
frame = new JFrame("逗比聊天室 by Puter");
frame.getContentPane().setFont(new Font("楷体", Font.BOLD, 18));
frame.getContentPane().setForeground(Color.BLACK);
frame.setForeground(Color.RED);
frame.setTitle("\u8BA8\u8BBA\u7EC4");
frame.setBounds(450, 150, 994, 631);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JLabel label = new JLabel("\u9017\u6BD4\u804A\u5929\u5BA4");
label.setFont(new Font("楷体", Font.BOLD, 30));
label.setForeground(Color.RED);
label.setBounds(383, 23, 186, 50);
frame.getContentPane().add(label);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(246, 110, 466, 332);
frame.getContentPane().add(scrollPane);
textArea.setBackground(Color.BLACK);
textArea.setFont(new Font("楷体", Font.BOLD, 17));
scrollPane.setViewportView(textArea);
textArea.setEnabled(false);
final JButton btnNewButton = new JButton("\u53D1\u9001");
btnNewButton.setFont(new Font("宋体", Font.BOLD, 15));
btnNewButton.setForeground(Color.GREEN);
btnNewButton.setBounds(629, 484, 83, 40);
frame.getContentPane().add(btnNewButton);
textField_1 = new JTextField();
textField_1.setFont(new Font("楷体", Font.BOLD, 17));
textField_1.setBounds(246, 484, 361, 40);
frame.getContentPane().add(textField_1);
textField_1.setColumns(10);
try {
client = new Socket("localhost",8888) ;
} catch (IOException e) {
e.printStackTrace();
}
try {
out = new PrintStream(client.getOutputStream()) ;
} catch (IOException e) {
e.printStackTrace();
}
new Thread(new OutInfo(this.textArea,client)).start(); //线程时刻刷新聊天界面(客户端的精华后面附上)
lblNewLabel.setForeground(Color.RED);
lblNewLabel.setFont(new Font("新宋体", Font.BOLD, 24));
lblNewLabel.setBounds(29, 115, 180, 40);
frame.getContentPane().add(lblNewLabel);
if(textField_1.getText() != null){
btnNewButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
if(textField_1.getText() != null){
out.println(textField_2.getText()+"说:"+textField_1.getText());
textField_1.setText("");
}
}
});
}
}
}
package .client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import .Socket;
import javax.swing.JTextArea;
public class OutInfo implements Runnable { //客户端的精华-实现部分
private JTextArea t = null ; //向界面显示信息
private Socket client = null ;
private BufferedReader buf = null ;
public OutInfo(JTextArea t,Socket client){
this.t = t ;
this.client = client ; //界面传过来实例化
}
@Override
public void run() { //线程
boolean flag = true ;
String str = null ;
try {
buf = new BufferedReader(new InputStreamReader(client.getInputStream())) ;
} catch (IOException e) {
e.printStackTrace();
}
while(flag){ //一直监听服务器端口接收信息
synchronized(this){
try {
str = buf.readLine() ; //接收
} catch (IOException e) {
e.printStackTrace();
}
if(str!=null){
System.out.println(str);
t.append(str+"\n"); //显示
}
}
}
}
}
五、结论
收货很多,学会了团队合作的重要性,也熟悉了业务开发流程,更重要的是这是对自己所学的一种总结。词程序最主要困难的地方就是服务器要发给所有的客户端,和客户端要时刻更新接收到服务器的信息。
六、实验分工
姓名
分工
王科茗、冯娇
报告书综合整理和程序测试
王科茗
制作流程图和一些资料查找
冯娇
资料查找及任务书的整理
王科茗
程序查找和调试及资料整合
冯娇
前端程序的界面部分
王科茗
后端具体的实现和前端的结合
王科茗:55%(+-5%)
冯娇:45%(+-5%)
七、参考文献
[1]朱福喜.《Java语言程序设计》(第二版).科学出版社
[2]陈国君等.《Java程序设计基础》(第二版).清华大学出版社
[3] Deitel.《Java大学基础教程》(第六版).电子工业出版社
[4] MaryCampione.《Java语言导学》(第四版).机械工业出版社
[5] Y.Daniel Liang.《Java语言程序设计基础篇》(第六版). 机械工业出版社
[6] Kathy Sierra.《Head First Java》(第二版).东南大学出版社
源代码(先启动服务器才能启动客户端,局域网内通讯是客户端的“localhost”改为“服务器所在电脑的IP地址”):
服务器:
package .server;
import java.io.IOException;
import .ServerSocket;
import .Socket;
import java.util.ArrayList;
import java.util.List;
import .server.thread.ThreadServer;
public class Server {
private ServerSocket server = null ;
public static List<Socket> list = new ArrayList<Socket>() ;
private Socket client = null ;
private int count = 0 ;
public Server(){
try {
server = new ServerSocket(8888) ;
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("等待服务器被连接······");
boolean flag = true ;
while(flag){
synchronized(this){
try {
client = server.accept() ;
count++;
} catch (IOException e1) {
e1.printStackTrace();
}
list.add(client) ;
System.out.println("第"+count+"客户端被连接!");
try {
new Thread(new ThreadServer(client)).start();
} catch (Exception e) {
e.printStackTrace();
flag = false ;
}
}
}
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package .server.start;
import .server.Server;
public class ServerStart {
public static void main(String[] args) {
new Server();
}
}
package .server.thread;
impor
展开阅读全文