01.项目分析

这个项目利用Socket、ServerSocket、DatainputStream、DataOutputStream、Thread以及GUI技术,开发一个简单聊天室应用程序。图1显示这个聊天室程序本机模拟运行后的典型结果。其中可以看到服务器接受两个用户以及显示两个用户的对话过程。下图是在本机操作系统窗口运行一个聊天用户的截图。

图1 聊天室两个用户对话截图

类的设计:

在下面的代码解释中将详细讨论主要类和方法的设计目的编写技术。这里将项目中的两大类:服务端类ChatServer以及用户端类ChatClient做一个概括性描述。

ChatServer——利用ServerSocket创建连接、监控用户端连接端口、利用API类Vector管理和协调多用户端的请求与对话操作,以及各种异常处理。

ChatClient——利用Socket创建对服务端ServerSocket的连接和异常处理、运行时得到用户名以及显示、利用GUI组件创建聊天室窗口、布局、显示聊天内容以及事件处理。利用线程执行对多聊天用户的协调处理和操作等。ChatClient包括如下内部类:

WindowExitHandler——执行按下Exit按钮时的关闭聊天室窗口操作。

TextActionHandler——执行将输入的聊天信息显示到每个用户聊天室窗口的功能。

ChatClientReceive——执行聊天用户线程之间聊天信息的协调性显示以及运行。

实战项目测试和模拟运行:

建议你首先在本机对这个实战项目进行模拟试运行。服务端程序可在Eclipse或者本机操作系统运行;然后打开两到三个本机操作系统窗口,按照图1下图运行用户端程序。

以下是用户端程序的主要代码部分:

void client() { //自定义方法执行用户连接和线程创建try {if(hostname.equals("local"))hostname=null;InetAddress serverAddr= InetAddress.getByName(hostname);sock=new Socket(serverAddr.getHostName(), port); //按指定地址和端口创建SocketremoteOut=new DataOutputStream(sock.getOutputStream()); //创建输出流System.out.println("Connected to server " + serverAddr.getHostName() //打印信息+ " on port " + sock.getPort() + " user: " + username);new ChatClientReceive(this).start(); //创建用户线程准备执行}catch(IOException e) {System.out.println(e.getMessage() + " : Failed to connect to server.");}
}
class TextActionHandler implements ActionListener {//处理文本框聊天信息事件和发送信息到服务器public void actionPerformed(ActionEvent e) {try  {if (e.getSource() == sendText) { //如果是文本框触发事件remoteOut.writeUTF(username + "->" + sendText.getText()); //发送信息receivedText.append("\n" + username + "->" + sendText.getText());//显示到本机sendText.setText(""); //清除文本框内容}}catch(IOException x) {System.out.println(x.getMessage() + " : connection to peer lost.");}}}
}
class ChatClientReceive extends Thread { //处理用户接收聊天室信息线程private ChatClient chat;ChatClientReceive(ChatClient chat) { //构造方法this.chat=chat;}public synchronized void run() { //应用协调覆盖run()方法String s;DataInputStream remoteIn=null;try {remoteIn= new DataInputStream(chat.sock.getInputStream()); //创建接收信息数据流while(true) {s = remoteIn.readUTF(); //按UTF方式读入信息chat.receivedText.append("\n" + s); //添加到文本窗口}}catch(IOException e) {System.out.println(e.getMessage() + " : connection to peer lost.");}}
}

用户端主方法创建GUI窗口以及ChatClient对象如下:

//聊天室用户端主方法代码
public static void main(String args[]) {JFrame frame= new JFrame("Connecting to Dear "+args[0]); //利用指令参数指定用户名ChatClient chat=new ChatClient(frame,args[0],"localhost"); //创建用户frame.add("Center",chat); //注册聊天室窗口frame.setSize(350,600); //指定大小frame.setResizable(false); //不可变更frame.setVisible(true); //显示窗口chat.client(); //调用client()方法}

代码中利用指令行参数args[0]来指定用户名。所以必须在操作系统窗口利用java指令运行这个用户端程序。例如:

java ChatClient UserName //打入具体用户名,如 Emily

如下是聊天室服务器端程序的主要代码:

//
...
public class ChatServer { //聊天室服务器端程序private static final int port = 1688; //指定端口private boolean connected = true; //假设连接无误private Vector<DataOutputStream> clients=new Vector<DataOutputStream>(); //创建用户队列public static void main(String args[]) {new ChatServer().server(); //创建无名服务器对象并调用方法server()}
void server() { //自定义方法执行连接用户和聊天室操作ServerSocket serverSock = null;try {InetAddress serverAddr=InetAddress.getByName(null); //地址初始化System.out.println("Welcome to Chat Server. The server is running..."); //显示运行信息System.out.println("Waiting for " + serverAddr.getHostName() + " on port "+ port);serverSock=new ServerSocket(port, 50); //聊天室最大用户为50, 可以是任何整数catch(IOException e) {System.out.println(e.getMessage()+": Disconnected/Failed");}while(connected) {try {Socket socket=serverSock.accept(); //接受用户连接请求System.out.println("Accept"+socket.getInetAddress()getHostName()); //显示信息//如下代码行创建输出流DataOutputStream remoteOut= new DataOutputStream(socket.getOutputStream());clients.addElement(remoteOut); //将一个用户加入聊天室队列new ServerHelper(socket,remoteOut,this).start();//启动这个用户的线程}catch(IOException e) {System.out.println(e.getMessage()+": Disconncted/Failed");}}}synchronized Vector getClients() { //自定义方法返回用户队列return clients;}synchronized void removeFromClients(DataOutputStream remoteOut){ //删除推出聊天室用户clients.removeElement(remoteOut);}
}

虽然在这个代码中规定聊天室最大用户容量为50,这个数量可根据网络速度调整。代码中利用Vector对象来记录聊天室中的用户对象,以便向所有聊天室用户发送对话信息。每一个用户都是一个独立的线程,由其创建一个无名ServerHelper对象,并调用其start()方法来启动执行。因为在调用自定义方法getClients()和removeFromClients()时存在多线程协调问题,所以应用协调操作synchronized。

如下是自定义类ServerHelper的代码:

//聊天室服务器端用来协调处理用户聊天信息I/O的线程
class ServerHelper extends Thread {private Socket sock;private DataOutputStream remoteOut;private ChatServer server;private boolean connected = true;private DataInputStream remoteIn;//构造器对服务器和输入聊天室信息的用户初始化ServerHelper(Socket sock,DataOutputStream remoteOut,ChatServer server) throws IOException {this.sock=sock;this.remoteOut=remoteOut;this.server=server;remoteIn=new DataInputStream(sock.getInputStream());}public synchronized void run() { //覆盖run()方法并协调运行String s;try {while(connected) {s = remoteIn.readUTF(); //读入一个用户输入信息broadcast(s); //传播这个信息到所有聊天室用户}}catch(IOException e) {System.out.println(e.getMessage()+"connection failed");}}private void broadcast(String s) { //自定义方法执行聊天室信息传播Vector clients=server.getClients(); //得到聊天室所有用户DataOutputStream dataOut=null; //声明输出流for(Enumeration e=clients.elements(); e.hasMoreElements(); ) { //对每一个聊天室用户dataOut=(DataOutputStream)(e.nextElement()); //得到用户输出流对象if(!dataOut.equals(remoteOut)) { //如果不是删除用户try {dataOut.writeUTF(s); //输出这个聊天室信息}catch(IOException x) {System.out.println(x.getMessage()+"Failed");server.removeFromClients(dataOut);}}}}
}

可以看到,由于在Vector的队列中储存有所有聊天室用户输出流信息,因而容易实现对聊天室所有用户传播对话信息。当某个用户在聊天室输入任何对话后,这个信息作为参数,传入自定义方法broadcast()中,并利用循环和枚举技术,遍历用户队列,执行向所有用户传播这个对话信息的操作。由于方法run()有可能在同一时间被多个用户运行的情况,代码中利用synchronized来实现这个协调。

手把手教会你 | 多用户-服务器聊天室应用软件开发相关推荐

  1. FluorineFx + Flex视频聊天室案例开发----客户端

    上一篇<FluorineFx + Flex视频聊天室案例开发----服务器端>详细的介绍了如何利用FluorineFx开发一个及时通信的视频聊天室服务器处理程序,并通过Web网站来宿主这个 ...

  2. Flex与.NET互操作(十六):FluorineFx + Flex视频聊天室案例开发

    本文将使用FluorineFx和Flex结合介绍一个简单的视频聊天室案例开发,希望通过此篇和大家交流FluorineFx和Flex的相关技术,同时也希望本篇可以帮助到需要使用FluorineFx做及时 ...

  3. 仿微信的网络聊天室项目开发【完整源码讲解】

    目录 总体开发思路 服务器端 服务器界面设计 建立TCP服务器端通信 建立服务器消息发送输出流 建立服务器消息接收输入流 建立服务器实时消息通信线程 设置服务器通信自由断开 客户端 客户端界面设计 建 ...

  4. 【python】基于Socket的聊天室Python开发

    基于Socket的聊天室Python开发 一.Socket简述 二.创建服务端Server 2.1 创建服务端初始化 2.2 监听客户端连接 2.3 处理客户端消息 三.创建客户端Client 3.1 ...

  5. FMS视频聊天室的开发

    FMS视频聊天室的开发 2009年06月07日 由于FLASH技术的发展, FLASH对本地P2P的支持,越来越进这就出现了FMS FLASH视频聊天室的开发. flash聊天室,fms聊天室源码 一 ...

  6. 视频教程-Java基础中国象棋和网络聊天室Swing开发-Java

    Java基础中国象棋和网络聊天室Swing开发 IT行业资深从业者,7年资深Java高级开发,Java架构师.曾就职银行.电信等行业多家上市公司.担任项目负责人,软件架构师.有丰富的高并发.分布式系统 ...

  7. 多人私密视频直播会议聊天室系统开发

    多人视频直播会议聊天室系统开发 轻便小巧无须安装 绑定公号无须登录 界面简洁操作方便 权限管理避免白嫖 前端/ 会议设置 用户可以设置姓名 管理员可以修改会议主题和分享说明文字 多人视频 左上显示用户 ...

  8. vue 文字无缝滚动_手把手教你搭建 Vue 聊天室

    WebSocket简介 WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单,并且允许服务端主动向客户端推送数据.(HTTP协 ...

  9. 使用python基于socket的tcp服务器聊天室

    # coding=utf-8 import socket,threading,time '''代码说明:1.创建一个字典用于接受客户端的用户名和信息2.创建一个类对象client用于编写客户端套接字对 ...

  10. 仿微信的网络聊天室项目开发【完整源码讲解,Java一年工作经验面试题

    /*使滚动条置于文本框最下端*/ infoWindow.setSelectionStart(infoWindow.getText().length());JScrollBar jSBInfo = jS ...

最新文章

  1. HighNewTech:18.11.07—第五届世界互联网大会—互联网届的奥斯卡大奖—15张PPT见证15项世界互联网领先科技成果
  2. 零件分组pascal程序
  3. QT的QDrag类的使用
  4. Android Studio中关于9-patch格式图片的编译错误
  5. java jstat 命令_java高分局之jstat命令使用(转)
  6. some ubuntu shell commands
  7. MongoDB自学日记1——基本操作
  8. VirtualBox安装MACOSX 10.13虚拟机的增强功能
  9. python垃圾分类游戏_垃圾分类就要来了?教你使用Python轻松完成垃圾分类
  10. 为何Emacs和Vim被称为两大神器
  11. 当前计算机与医学结合的研究热点,浅谈医学影像技术的现在与未来论文范文
  12. 温故知新|传感器基础结构与通信原理
  13. 干货 | 深度理解数据采集与埋点,提高自主数据分析能力!
  14. 详解34家银行对公账号编码规则及其编码分析
  15. 动态时间规整算法DTW
  16. 章泽天加入微软实习 网友:提升程序员整体形象
  17. UI设计界面设计培训班
  18. Linux连接工具(一)XShell7(免费版)下载及安装步骤
  19. cad快看_CAD看图软件览图模式及其功能介绍
  20. 据说三分之一左右的小米盒子安装了第三方兔子桌面?

热门文章

  1. android真机调试工具,ADB 安卓真机调试工具
  2. MyBatis操作数据库
  3. python因子分析 ic值 函数_spss问卷调查因子分析定义变量及内容输入
  4. 使用Java的JNI调用C
  5. iir数字滤波器设计及matlab实现,终稿毕业论文:IIR数字滤波器设计及其MATLAB实现.docOK版(样例3)...
  6. 惠普计算机X9W2AV参数,MAX220CPE,MAX220CPE pdf中文资料,MAX220CPE引脚图,MAX220CPE电路-Datasheet-电子工程世界...
  7. 原子结构示意图全部_原子结构示意图和元素及元素周期表
  8. 计算机专业学微机原理与接口技术,信息技术学院计算机科学与技术专业《微机原理与接口技术.doc...
  9. 腾讯QQ空间登录的方法实现方式与验证过程分析
  10. 基于SSM的企业人事管理系统(Spring+SpringMVC+Mybatis)