开放实验报告
学院: 计算机电子信息工程学院 专业: 计算机科学与技术 班级: 11级计算机科学与技术本科一班 学号 201101010023 姓名: 邵 帅
一、开放实验项目
Java项目开发—Chat即时聊天系统
二、开放实验时间
2012.11.07—2012.11.28 三、开放实验地点 专业微机室二(B-4009) 四、开放实验目的
综合利用JDK、Eclipse开发环境,实现中小型项目的设计。
本系统采用C/S架构,基于TCP协议实现数据在服务器和客户端之间进行传输,实现聊天信息的存储。
通过“Chat即时聊天系统”的设计过程,深刻了解掌握面向对象程序设计语言Java的核心概念和特性;了解编程技术知识,学会处理异常状况,深入了解Java数据库功能,熟练掌握图形界面的操作技术,掌握Java应用软件的开发环境和开发过程;灵活选择程序设计思想,在编写过程中进一步体会Java与其它编程语言的不同之处,分析出Java的优点和先进之处。同时,使学生能够深入的了解软件项目开发的流程和步骤,掌握每一部分的设计和实现方法,以及充分利用现有的软件工程设计工具来完成项目的设计。
五、开放实验内容 1.概要设计
采用Socket类建立套接字实现客户端与服务端的通讯。 总体数据流图
发送请求 返回回应 客户端数据流图 客户端 服务端 发出连接信号
1
客户端 发送消息 接收并显示消息
服务端数据流图
接受并显示消息
服务端
发送消息 2.设计原理
(1).利用多线程实现多客户机制。服务器总是在指定的端口上监听是否有客户请求,一旦监听到客户请求,服务器就会启动一个专门的服务线程来响应该客户的请求,而服务器本身在启动完线程之后马上又进入监听状态,等待下一个客户的到来。 (2).
服务器在接受客户方的请求后,立即高度一个线程以处理服务器与客 在服务器的程序中首先创建单个Server Socket,并调用accept()来
户方之间的交互,主程序则返回继续监听端口,等待下一个客户的连接请求。前一个线程在完成相应的交互过程后自动退出,连接也将自动关闭。 (3).
等候一个新连接,一旦accept()返回,就取得获得结果的Socket,并用它新建一个线程,令其只为那个特定的客户提供服务。然后再调用accept(),等候下一个新的连接请求。 3.客户端设计
(1)、 数据流图
创建客户端Socket .
发送请求数据,调 接收响应数据 用write() 向服务器发送请求,调用connect() 定义Client类控制客户端,用于实现客户端的接收信息与发送信息等操作
2
(2)、客户端代码 import java.net.*; import java.io.*;
public class Client extends Thread {
Socket skt; // 用于客户端的连接 InetAddress host; // 主机地址 int port; // 端口号 BufferedReader theInputStream; PrintStream theOutputStream; String readin; Face chat;
public Client(String ip, int p, Face chat) { try {
host = InetAddress.getByName(ip); // 获取IP地址 port = p; // 获取端口号 this.chat = chat; } catch (IOException e) { chat.ta.append(e.toString()); } }
public void run() { try {
chat.ta.append(\"准备连线,稍后!\");
skt = new Socket(host, port); // 新建Socket对象 chat.ta.append(\"成功\\n\"); // 缓冲区末尾添加字符串 theInputStream
=
new
BufferedReader(new
InputStreamReader(skt.getInputStream()));
theOutputStream = new PrintStream(skt.getOutputStream()); while (true) {
readin = theInputStream.readLine();
3
chat.ta.append(readin + \"\\n\"); }
} catch (SocketException e) { chat.ta.append(\"未连上!\\n\"); chat.clientBtn.setEnabled(true); chat.serverBtn.setEnabled(true); chat.tfaddress.setEnabled(true); chat.tfport.setEnabled(true); try {
skt.close();
} catch (IOException err) { chat.ta.append(err.toString()); }
} catch (IOException e) { chat.ta.append(e.toString()); } }
public void dataout(String data) { theOutputStream.println(data); } }
4、服务端的设计 (1)、 数据流图
返回相应的数据,调用write() 处理请求数据 接收来自客户端的数据,read() 创建服务端Socket 联编到某一个端口,调用bin() 监听来自客户端的请求,调用listen() 组塞,等待客户端请求,accpt() 定义Server类控制服务端,用于实现服务端的接收信息和发送信息等操作
4
(2)、 服务端代码 import java.awt.*; import java.net.*; import java.io.*;
public class Server extends Thread {
ServerSocket skt; // ServerSocket类监听进入的连接,为每个新的连接产生一个Socket对象
Socket Client[ ]=new Socket[10]; Socket Client1=null; int i = 0; TextArea in; int port,k=0,l=0;
PrintStream theOutputStream; Face chat;
public Server(int port, Face chat) { try {
this.port = port;
skt = new ServerSocket(port); this.chat = chat; } catch (IOException e) { chat.ta.append(e.toString()); } }
public void run() {
chat.ta.append(\"等待连线......\"); while (true) { try {
Client[k] = skt.accept();
//当有客户端连接时就新建一个子线程 if (i < 2) {
5
ServerThread server[] = new ServerThread[10]; server[k]= new ServerThread(Client[k], this.chat, i); l=server.length; server[k].start();
chat.ta.append(\"客户端\"+ Client[k].getInetAddress() + \"已连线\\n\"); //for(int j=0;j //theOutputStream = new PrintStream(null); } } catch (SocketException e) { } catch (IOException e) { chat.ta.append(e.toString()); } } } public void dataout(String data) { //for(int j=0;j class ServerThread extends Thread { ServerSocket skt; Socket Client; TextArea in; int port,i; BufferedReader theInputStream; 6 new PrintStream theOutputStream; String readin; Face chat; public ServerThread(Socket s, Face chat, int i) { this.i = ++i; Client = s; this.chat = chat; } public int getI() { return this.i; } public Socket getClient() { return this.Client; } public void run() { try { theInputStream = new BufferedReader(new InputStreamReader(Client.getInputStream())); theOutputStream = new PrintStream(Client.getOutputStream()); while (true) { readin = theInputStream.readLine(); chat.ta.append(readin + \"\\n\"); } } catch (SocketException e) { chat.ta.append(\"连线中断!\\n\"); // 设置组件可用性 chat.clientBtn.setEnabled(true); chat.serverBtn.setEnabled(true); chat.tfaddress.setEnabled(true); chat.tfport.setEnabled(true); try { 7 i --; skt.close(); Client.close(); } catch (IOException err) { chat.ta.append(err.toString()); } } catch (IOException e) { chat.ta.append(e.toString()); } } public void dataout(String data) { theOutputStream.println(data); } } 5、聊天界面的设计 (1)、通过调用Face类对界面进行管理设计,运用Button、TextArea、Label等组件,然后通过actionPerformed触发事件来完成操作。 (2)、界面代码 import java.awt.*; import java.awt.event.*; public class Face extends Frame { private static final long serialVersionUID = 1L; Button clientBtn, serverBtn; TextArea ta; TextField tfaddress, tfport, tftype,tfname; Label lbl1,lbl2,lbl3,lbl4; int port; Client client; Server server; boolean iamserver; 8 static Face frm; public Face() { //实例化组件 clientBtn = new Button(\"客户端\"); serverBtn = new Button(\"服务器\"); ta = new TextArea(\"\ lbl1 = new Label(\"IP地址:\"); tfaddress = new TextField(\"127.0.0.1\ lbl2 = new Label(\"端口:\"); tfport = new TextField(\"8888\"); lbl3 = new Label(\"发送内容:\"); tftype = new TextField(25); lbl4=new Label(\"昵 称:\"); tfname=new TextField(30); tftype.addKeyListener(new TFListener()); ta.setEditable(false); //向容器中加入以上组件 setLayout(new FlowLayout()); add(lbl1); add(tfaddress);add(lbl2);add(tfport);add(serverBtn); add(clientBtn);add(lbl4);add(tfname);add(ta);add(lbl3);add(tftype); //设置格式 setLocation(350, 250); //窗口显示在屏幕的位置坐标 setSize(400, 320); //设置窗体大小 setTitle(\"图形界面的聊天程序\"); this.setVisible(true); //设置窗体可见 clientBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { port = Integer.parseInt(tfport.getText()); client = new Client(tfaddress.getText(), port, frm); client.start(); 9 tfaddress.setEnabled(false); tfport.setEnabled(false); serverBtn.setEnabled(false); clientBtn.setEnabled(false); tfname.setText(\"客户端\"); } }); //客户端事件响应 serverBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { port = Integer.parseInt(tfport.getText()); server = new Server(port, frm); server.start(); iamserver = true; tfaddress.setText(\"成为服务器\"); tfaddress.setEnabled(false); tfport.setEnabled(false); serverBtn.setEnabled(false); clientBtn.setEnabled(false); tfname.setText(\"服务器\"); } }); //服务器端事件响应 addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); //窗口事件响应 } public static void main(String[] args) { //主方法 frm = new Face(); } 10 private class TFListener implements KeyListener { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { //按Enter输出显示聊天内容 if (iamserver){ } else{ ta.append(tfname.getText()+\":\\n\" + tftype.getText() + \"\\n\"); client.dataout(tfname.getText()+\":\\n\" +tftype.getText()); tftype.setText(\"\"); } } } public void keyTyped(KeyEvent e) { } public void keyReleased(KeyEvent e) { } } } 6、测试与运行结果 服务端的界面 ta.append(tfname.getText()+\":\\n\" + tftype.getText() + \"\\n\"); server.dataout(tfname.getText()+\":\\n\" +tftype.getText()); 11 客户端界面 六、开放实验总结 通过这次的开放实验课程,掌握了聊天软件的运行模式,丰富了我对java应用程序编写聊天系统的认识,通过“Chat即时聊天系统”的设计过程,我深刻地认识了在操作过程中,面向对象程序设计语言java的核心概念和特性,以及对异常状况的处理和图形用户界面的操作的优越性,感觉通过此次开放实验课更加让我对学习产生了动力,我希望它不仅仅是一个课程,更是我在学习程序设计中的一次进步,我会通过它去更加努力实现和掌握更多的知识。 12 因篇幅问题不能全部显示,请点此查看更多更全内容