当前位置:文档之家› java课程设计报告(java聊天室)

java课程设计报告(java聊天室)

Java聊天室课程设计一、需求分析1.1开发背景在信息化社会的今天,网络飞速发展,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的聊天工具越来越多,类似MSN、QQ,网络聊天时一类的聊天系统的发展日新月异,因此产生了制作一个类似QQ的网络聊天工具的想法,且通过制作该程序还能更好的学习网络软件编程知识。

网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯。

网编程中有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。

在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机。

而TCP层则提供面向应用的可靠的或非可靠的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的。

目前较为流行的网络编程模型是客户机/服务器(C/S)结构。

即通信双方一方作为服务器等待客户提出请求并予以响应。

客户则在需要服务时向服务器提出申请。

服务器一般作为守护进程始终运行,监听网络端口,一旦有客户请求,就会启动一个服务进程来响应该客户,同时自己继续监听服务端口,使后来的客户也得到响应的服务。

1.2设计要求本课程设计的目标是利用套接字socket()设计一个聊天程序,该程序基于C/S模式,客户机器向服务器发聊天请求,服务器应答并能显示客户机发过来的信息。

1.3设计目的通过设计一个网络聊天程序,对套接字、数据报通讯、URL、与URLConnectiom的相关知识有详细的了解和充分的认识。

能将相关的只是运用到相关的实践中去。

1.4功能实现聊天室共分为客户端和服务端两部分,服务器程序主要负责侦听客户端发来的消息,客户端需要登录到相应的服务器才可以实现正常的聊天功能。

服务器的主要功能有1)在特定端口上进行侦听,等待客户连接2)用户可以配置服务器的真挺端口3)向已经连接服务器的客户发送系统消息4)统计在线人数5)当停止服务时,断开所有用户的连接客户端的主要功能1)连接到已经开启聊天服务的服务端2)用户可以配置要连接服务器端的ip地址和端口号3)用户可以配置连接后显示的用户名4)当服务器开启时。

用户可以随时登陆和注销5)用户可以向所有人或一个人发送消息二、总体设计2.1设计思想套接字对象在网络编程中扮演者重要的角色,可以用套接字技术编写一个聊天室,服务器为每个客户启动一个线程。

在该线程中通过套接字和客户交流信息,当客户向服务器发送一条聊天信息“大家好”时,服务器要让所有的这些线程中的输入流写入信息大家好,这样所有的客户的套接字的输入流就都读取到了这一条信息。

如果把信息“你好”发送给特定用户,服务器就让特定线程中的输出流写入信息“你好”,那么只有特定客户的套机字的输入流可以读取到这条信息。

在聊天室中需要对用户上线下线的状态进行修改,进而统计在线人数、查找某用户等。

因而需要用到java链表来实现。

由于Java语言不像c或c++一样可以利用线性表的链式存储结构,用节点和指针来表示,在Java中是没有指针的,但是可以通过使用对象的引用来实现链表。

链表的结点个数称为链表的长度。

因此在Java中可以定义两个类来实现链表的操作,分别为节点类和链表类。

在本设计中对用户的存储就是利用链表来实现的。

2.2基本设计概念和处理流程本系统运行用JA V A开发,采用C\S结构,系统分为客服端和服务端两大模块,使用Socket 类建立套接字实现客服端和服务端得通讯。

处理流程服务端客户端一个ServerSocket对象和一个Socket对象一个Socketd对象TCP Socket通信流程2.3总体结构2.4功能分配客户端服务端2.5接口设计2.5.1用户接口提供一个用户操作界面:包括用户可以再界面中登录聊天室、输入消息、浏览聊天内容和聊天对象。

同时提供一个服务器操作界面,通过服务器操作界面可以修改服务器的配置,知道用户的当前状态,并可以给用户发送指定系统信息。

2.5.2内部接口Socket(string hont ,int port );客户端使用Socket类建立与服务器的套接字连接。

ServerSocket(int port);建立接收客户的套接字的服务器套接字。

2.6主要模块2.6.1聊天室服务器端模块聊天室服务器端模块主要有以下几部分组成1、主框架类(ChatServer.java)该文件包含名为ChatServer的public类,其主要功能是定义服务器的界面,添加事件侦听鱼事件处理。

ChatServer类调用ServerListen类来实现服务端用户上线与下线的侦听,调用ServerReceive类来实现服务器端消息的转发。

2、服务器用户上线与下线侦听类。

该类对用户上线与下线的侦听是通过调用用户链表类来实现的,当用户的上线与下线情况发生改变时,该类会对主类的界面进行相应的修改。

3、服务器消息收发类该类分别定义了向某用户及向所有人发送消息的方法,发送的消息会显示在主界面类的界面上。

4用户修改配置的类。

该类继承自JDialog。

使用户对服务器端口进行修改配置的类。

5节点类定义了链表中的用户6链表类该类通过构造函数构造用户链表,定义了添加用户、删除用户、返回用户数、根据用户名查找用户和各根据索引查找用户等方法。

7服务器帮助类、2.6.2聊天室服务器端模块算法描述服务器端的ChatServer类继承自JFrame并实现相应的事件监听接口,因此它定义了服务器的主框架,及各个按钮的事件监听。

它分别调用ServerListen类来实现服务端用户上线与下线的侦听,调用ServerReceive类来实现服务器端消息的转发。

同时服务器可以响应多个客户的请求,当一个客户发送请求时,服务器就为它增加一个线程,同时服务器利用UserLinkList类为客户端设置一个请求队列,如果服务器不能马上响应客户端的请求,就要把这个请求放到请求队列在中,,等服务器将当前的请求处理完,会自动到请求队列中按照先后顺序取出请求进行处理。

2.6.3聊天室客户端模块客户端主要有以下几个文件,功能如下:1客户端主框架类该类主要定义客户端的界面,添加事件侦听与事件处理。

该类定义了与服务器实现连接与断开连接的方法。

当用户登录到指定的服务器上时,该类条用客户端实现消息收发的类实现消息的收发。

同时该类定义了向所有用户发送消息的方法。

2客户端消息收发的类该类实现了服务器与客户端消息的收发3用户修改配置的类该类继承自JDialog,是用户对要连接的服务器IP及侦听端口进行修改配置的类。

4帮助类客户端用户程序的帮助类2.6.4聊天室客户端模块主要算法描述客户端ChatClient类继承了JFrame并实现相应的事件监听接口。

它实现了客户端的主界面及相应按钮的事件侦听。

该类调用ClientReceive类实现消息的收发。

同时该类定义了向所有用户发送消息的方法。

通过相应的输入输出流与服务器进行数据的传递与交流。

三、主要代码实现3.1服务器主要代码实现1、Chatserver类:包含名为ChatServer的public类,其主要功能为定义服务器端的界面,添加事件侦听与事件处理。

调用ServerListen类来实现服务端用户上线与下线的侦听,调用ServerReceive类来实现服务器端的消息的收发。

import java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.event.*;import .*;import java.io.*;/** 聊天服务端的主框架类*/public class ChatServer extends JFrame implements ActionListener{public static int port = 8888;//服务端的侦听端口ServerSocket serverSocket;//服务端SocketImage icon;//程序图标JComboBox combobox;//选择发送消息的接受者JTextArea messageShow;//服务端的信息显示JScrollPane messageScrollPane;//信息显示的滚动条JTextField showStatus;//显示用户连接状态JLabel sendToLabel,messageLabel;JTextField sysMessage;//服务端消息的发送JButton sysMessageButton;//服务端消息的发送按钮UserLinkList userLinkList;//用户链表//建立菜单栏JMenuBar jMenuBar = new JMenuBar();//建立菜单组JMenu serviceMenu = new JMenu ("服务(V)");//建立菜单项JMenuItem portItem = new JMenuItem ("端口设置(P)");JMenuItem startItem = new JMenuItem ("启动服务(S)");JMenuItem stopItem=new JMenuItem ("停止服务(T)");JMenuItem exitItem=new JMenuItem ("退出(X)");JMenu helpMenu=new JMenu ("帮助(H)");JMenuItem helpItem=new JMenuItem ("帮助(H)");//建立工具栏JToolBar toolBar = new JToolBar();//建立工具栏中的按钮组件JButton portSet;//启动服务端侦听JButton startServer;//启动服务端侦听JButton stopServer;//关闭服务端侦听JButton exitButton;//退出按钮//框架的大小Dimension faceSize = new Dimension(400, 600);ServerListen listenThread;JPanel downPanel ;GridBagLayout girdBag;GridBagConstraints girdBagCon;/*** 服务端构造函数*/public ChatServer(){init();//初始化程序//添加框架的关闭事件处理this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.pack();//设置框架的大小this.setSize(faceSize);//设置运行时窗口的位置Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();this.setLocation( (int) (screenSize.width - faceSize.getWidth()) / 2,(int) (screenSize.height - faceSize.getHeight()) / 2);this.setResizable(false);this.setTitle("聊天室服务端"); //设置标题//程序图标icon = getImage("icon.gif");this.setIconImage(icon); //设置程序图标show();//为服务菜单栏设置热键'V'serviceMenu.setMnemonic('V');//为端口设置快捷键为ctrl+pportItem.setMnemonic ('P');portItem.setAccelerator (KeyStroke.getKeyStroke(KeyEvent.VK_P,InputEvent.CTRL_MASK));//为启动服务快捷键为ctrl+sstartItem.setMnemonic ('S');startItem.setAccelerator (KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK));//为端口设置快捷键为ctrl+TstopItem.setMnemonic ('T');stopItem.setAccelerator (KeyStroke.getKeyStroke(KeyEvent.VK_T,InputEvent.CTRL_MASK));//为退出设置快捷键为ctrl+xexitItem.setMnemonic ('X');exitItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_X,InputEvent.CTRL_MASK));//为帮助菜单栏设置热键'H'helpMenu.setMnemonic('H');//为帮助设置快捷键为ctrl+phelpItem.setMnemonic ('H');helpItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_H,InputEvent.CTRL_MASK));}/*** 程序初始化函数*/public void init(){Container contentPane = getContentPane();contentPane.setLayout(new BorderLayout());//添加菜单栏serviceMenu.add (portItem);serviceMenu.add (startItem);serviceMenu.add (stopItem);serviceMenu.add (exitItem);jMenuBar.add (serviceMenu);helpMenu.add (helpItem);jMenuBar.add (helpMenu);setJMenuBar (jMenuBar);//初始化按钮portSet = new JButton("端口设置");startServer = new JButton("启动服务");stopServer = new JButton("停止服务" );exitButton = new JButton("退出" );//将按钮添加到工具栏toolBar.add(portSet);toolBar.addSeparator();//添加分隔栏toolBar.add(startServer);toolBar.add(stopServer);toolBar.addSeparator();//添加分隔栏toolBar.add(exitButton);contentPane.add(toolBar,BorderLayout.NORTH);//初始时,令停止服务按钮不可用stopServer.setEnabled(false);stopItem .setEnabled(false);//为菜单栏添加事件监听portItem.addActionListener(this);startItem.addActionListener(this);stopItem.addActionListener(this);exitItem.addActionListener(this);helpItem.addActionListener(this);//添加按钮的事件侦听portSet.addActionListener(this);startServer.addActionListener(this);stopServer.addActionListener(this);exitButton.addActionListener(this);combobox = new JComboBox();combobox.insertItemAt("所有人",0);combobox.setSelectedIndex(0);messageShow = new JTextArea();messageShow.setEditable(false);//添加滚动条messageScrollPane = new JScrollPane(messageShow,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); messageScrollPane.setPreferredSize(new Dimension(400,400)); messageScrollPane.revalidate();showStatus = new JTextField(35);showStatus.setEditable(false)sysMessage = new JTextField(24);sysMessage.setEnabled(false);sysMessageButton = new JButton();sysMessageButton.setText("发送");//添加系统消息的事件侦听sysMessage.addActionListener(this);sysMessageButton.addActionListener(this);sendToLabel = new JLabel("发送至:");messageLabel = new JLabel("发送消息:");downPanel = new JPanel();girdBag = new GridBagLayout();downPanel.setLayout(girdBag);girdBagCon = new GridBagConstraints();girdBagCon.gridx = 0;girdBagCon.gridy = 0;girdBagCon.gridwidth = 3;girdBagCon.gridheight = 2;girdBagCon.ipadx = 5;girdBagCon.ipady = 5;JLabel none = new JLabel(" ");girdBag.setConstraints(none,girdBagCon);downPanel.add(none);girdBagCon = new GridBagConstraints();girdBagCon.gridx = 0;girdBagCon.gridy = 2;girdBagCon.insets = new Insets(1,0,0,0);girdBagCon.ipadx = 5;girdBagCon.ipady = 5;girdBag.setConstraints(sendToLabel,girdBagCon); downPanel.add(sendToLabel);girdBagCon = new GridBagConstraints();girdBagCon.gridx =1;girdBagCon.gridy = 2;girdBagCon.anchor = GridBagConstraints.LINE_START; girdBag.setConstraints(combobox,girdBagCon); downPanel.add(combobox);girdBagCon = new GridBagConstraints();girdBagCon.gridx = 0;girdBagCon.gridy = 3;girdBag.setConstraints(messageLabel,girdBagCon); downPanel.add(messageLabel);girdBagCon = new GridBagConstraints();girdBagCon.gridx = 1;girdBagCon.gridy = 3;girdBag.setConstraints(sysMessage,girdBagCon); downPanel.add(sysMessage);girdBagCon = new GridBagConstraints();girdBagCon.gridx = 2;girdBagCon.gridy = 3;girdBag.setConstraints(sysMessageButton,girdBagCon); downPanel.add(sysMessageButton);girdBagCon = new GridBagConstraints();girdBagCon.gridx = 0;girdBagCon.gridy = 4;girdBagCon.gridwidth = 3;girdBag.setConstraints(showStatus,girdBagCon); downPanel.add(showStatus);contentPane.add(messageScrollPane,BorderLayout.CENTER); contentPane.add(downPanel,BorderLayout.SOUTH);//关闭程序时的操作this.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){stopService();System.exit(0);}}}}/*** 事件处理*/public void actionPerformed(ActionEvent e) {Object obj = e.getSource();if (obj == startServer || obj == startItem) { //启动服务端startService();}else if (obj == stopServer || obj == stopItem) { //停止服务端int j=JOptionPane.showConfirmDialog(this,"真的停止服务吗?","停止服务",JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE);if (j == JOptionPane.YES_OPTION){stopService();}}else if (obj == portSet || obj == portItem) { //端口设置//调出端口设置的对话框PortConf portConf = new PortConf(this);portConf.show();}else if (obj == exitButton || obj == exitItem) { //退出程序int j=JOptionPane.showConfirmDialog(this,"真的要退出吗?","退出",JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE);if (j == JOptionPane.YES_OPTION){stopService();System.exit(0);}}else if (obj == helpItem) { //菜单栏中的帮助//调出帮助对话框Help helpDialog = new Help(this);helpDialog.show();}else if (obj == sysMessage || obj == sysMessageButton) { //发送系统消息sendSystemMessage();}}/*** 启动服务端*/public void startService(){try{serverSocket = new ServerSocket(port,10);messageShow.append("服务端已经启动,在"+port+"端口侦听...\n");startServer.setEnabled(false);startItem.setEnabled(false);portSet.setEnabled(false);portItem.setEnabled(false);stopServer .setEnabled(true);stopItem .setEnabled(true);sysMessage.setEnabled(true);}catch (Exception e){//System.out.println(e);}userLinkList = new UserLinkList();listenThread = new ServerListen(serverSocket,combobox,messageShow,showStatus,userLinkList);listenThread.start();}/*** 关闭服务端*/public void stopService(){try{//向所有人发送服务器关闭的消息sendStopToAll();listenThread.isStop = true;serverSocket.close();int count = userLinkList.getCount();int i =0;while( i < count){Node node = userLinkList.findUser(i);node.input .close();node.output.close();node.socket.close();i ++;}stopServer .setEnabled(false);stopItem .setEnabled(false);startServer.setEnabled(true);startItem.setEnabled(true);portSet.setEnabled(true);portItem.setEnabled(true);sysMessage.setEnabled(false);messageShow.append("服务端已经关闭\n");combobox.removeAllItems();combobox.addItem("所有人");}catch(Exception e){//System.out.println(e);}}/*** 向所有人发送服务器关闭的消息*/public void sendStopToAll(){int count = userLinkList.getCount();int i = 0;while(i < count){Node node = userLinkList.findUser(i);if(node == null) {i ++;continue;}try{node.output.writeObject("服务关闭");node.output.flush();}catch (Exception e){//System.out.println("$$$"+e);}i++;}}/*** 向所有人发送消息*/public void sendMsgToAll(String msg){int count = userLinkList.getCount();//用户总数int i = 0;while(i < count){Node node = userLinkList.findUser(i);if(node == null) {i ++;continue;}try{node.output.writeObject("系统信息");node.output.flush();node.output.writeObject(msg);node.output.flush();}catch (Exception e){//System.out.println("@@@"+e);}i++;}sysMessage.setText("");}/*** 向客户端用户发送消息*/public void sendSystemMessage(){String toSomebody = combobox.getSelectedItem().toString();String message = sysMessage.getText() + "\n";messageShow.append(message);//向所有人发送消息if(toSomebody.equalsIgnoreCase("所有人")){sendMsgToAll(message);}else{//向某个用户发送消息Node node = userLinkList.findUser(toSomebody);try{node.output.writeObject("系统信息");node.output.flush();node.output.writeObject(message);node.output.flush();}catch(Exception e){//System.out.println(""+e);}sysMessage.setText("");//将发送消息栏的消息清空}/*** 通过给定的文件名获得图像*/Image getImage(String filename) {URLClassLoader urlLoader = (URLClassLoader)this.getClass().getClassLoader();URL url = null;Image image = null;url = urlLoader.findResource(filename);image = Toolkit.getDefaultToolkit().getImage(url);MediaTracker mediatracker = new MediaTracker(this);try {mediatracker.addImage(image, 0);mediatracker.waitForID(0);}catch (InterruptedException _ex) {image = null;}if (mediatracker.isErrorID(0)) {image = null;}return image;}public static void main(String[] args) {ChatServer app = new ChatServer();}}(2)ServerListen.java:该类实现服务端用户上线与下线的侦听。

相关主题