当前课程知识点:JAVA程序设计进阶 > 第五章 网络编程(下) > 5.4 网络聊天程序 > Video
这一节我们将介绍
网络聊天程序的内容
尤其是如何去实现
一个带界面的聊天程序
大家现在看到是一个
非常简单的一个
带界面的聊天程序
因为在前面的例子当中
我们已经写了一个
在命令行底下的聊天程序
那命令行聊天毕竟不是很方便
那既然我们java也能做界面
那何不把这个界面
和我们的网络通讯结合在一起
那我们先看一下这个
聊天程序的界面
那前面大家学过
用Swing来去构造
图形界面的话
那看到我们这个
当前这个界面的话
应该能想到怎么去构造它
从我们现在看到这个
界面的布局上面来说
有这么几个组件
最中间的话是一个文本区域
TextArea
那文本区域为了方便它滚动的话
那其实它有一个滚动面板
最下面的话是一个输入框
那输入框的话旁边有一个按钮
那整个这个布局
其实大家采用一个
BorderLayout就可以达到你的目标
那就是在BorderLayout的center
中间那区域
我们先放一个滚动面板
然后接着再放一个TextArea
然后在它的南部区域
我们先放一个Panel
紧接着再放一个TextView
文本输入区域
然后接着再放一个Button
而且TextView和Button的话
都是按照FlowLayout这种放置规则
意思放在中间
那我们看一下这个聊天程序里面
大家需要这个写的
事件响应是什么呢
其实首先最重要的是说
我们能够接收
这个在文本区域
就是最下面这个文本区域
这个输入的文本
那这个是TextView
那我们可以给TextView这个组件
来注册一个监听器
那当我们这个一回车
就在TextView里面
一输入字符一回车的时候
它产生的是一个ActionEvent
所以我们可以给
我们的TextView
注册一个EventListener
那TextView旁边的话
是一个按钮发送
其实发送的话
它所对应的这个事件处理
也是ActionEvent
所以在这个例子当中
我们只需要写一个事件处理类
然后都分别这个授权
来去处理TextView
和我们按钮的这么这个事件处理
就可以完成获得
我们这个文本的这么一个过程
以及把它发送的一个过程
那在这里面怎么去获得内容呢
TextView里面有个
一个getText的方法
那我们只要在我们的
ActionPerform方法里面
去通过TextView的getText
来获得它的内容
然后来决定一个是往外发送
同时把它显示到
当前我们的这个界面上面
那大家有没有观察到
这两个聊天的程序
一个左边是Cat 右边是Dog
也就是猫和狗在这个聊天
那注意的是我们每聊天
每次发送的这些信息的话
都会显示出是由Cat
还是Dog来说的
然后它发送的信息的时间
也显示出来了
那整个这个显示
实际上是在我们这个文本区域
TextArea来去进行显示的
所以每当有一次这个信息接收到
或者有输入到我们这个
文本区域的时候
我们就把它显示出来
下面我们看一下这个例子
那前面是import
一大堆我们需要用到的这个包
包括swing
包括我们的事件处理机制
包括我们的网络
包括我们的io
包括我们的util这个包
还有text
我们先看一下
我们写第一个类
public class ChatFrame
extends JFrame implements
我们构造出一个聊天的窗口
它继承于JFrame这个类
然后实现了
ActionListener这个接口
那我们在做这个
聊天窗口布局的时候
需要用到的下列这么些组件
第一个是JTextField
文本输入区域 文本输入框
用来我们接收
我们用户的聊天时候的输入
JTextArea
那JTextArea
是用来展示我们聊天过程的
所有的记录的
JScrollPane
是一个滚动面板
我们就是
由于我们的聊天记录会比较长
所以需要上下滚
来去看见聊天记录
所以我们构造JScrollPane
然后需要把JTextArea
放到这JScrollPane里面
那我们还有一个按钮 JButton
那就用来去发送
我们的聊天信息的
那我们还有一个面板Jpanel p
那主要是用来
放在我们整个界面的最下面
来去承载我们的JTextField
和我们的JButton
这两个类的对象
那我们看一下
我们这个程序的其它的成员变量
那在这部分的成员变量
主要是和我们的网络通讯相关的
首先我们定义了一个端口变量int
然后定义了一个字符串s为空
又定义了另外一个字符串myID
用来描述我这个聊天程序
所对应的这个用户的ID
然后我们有个Date对象
用来描述当前的这个时间
然后我们还有个ServerSocket
这个是一个服务器的
Socket对象server
然后另外还有个Socket对象
mySocket
那就是用来进行Socket连接的
那同时我们还构造了
这个身边有两个流
一个是BufferedReader is
另外一个PrintWriter os
那这个BufferedReader is
是用来接收输入的
而PrintWriter
是用来往外发送这个输出的
然后再一个定义了字符串
String line
好了 我们看看我们的ChatFrame这个类的构造方法
这个构造方法里面
有好几个参数
第一个String ID
也就是我自己的ID
String remoteID
是和我聊天的远程的
这个客户的ID
那String IP和int port
就是我们的这些地址
还有最后有一个这个
boolean isServer
那就是说我们在启动时候
需要确定到底谁
充当Server的功能
那这个构造方法里面
我们先调用了superID
调用了(负类)的构造方法
然后紧接着把myID
这个设置为我们参数中的ID
端口号port也用来设置
然后这个时候
我们要做一个界面的初始化了
ta等于new JTexarea
然后ta.setEditable false
我们把这个文本区域
设置为不可编辑
也是因为我们的文本区域
主要是用来显示
双方聊天的记录的使
sp等于new JScrollpane ta
那我们构造了
这么一个滚动面板的对象
然后它里面参数
就是我们那个文本区域ta
然后this.setSize330乘400
也就是设置
我们这个大小为330乘以400
然后this.setResizable false
也就是说我们这个窗口的话
是不能够改变它的这个大小的
那紧接着下面的话
我们要设置我们的显示风格
也就是UIManager.setLookAndFeel
然后它的显示风格的话
就是通过我们的系统的
这个显示风格
然后后面紧接着
就是捕获一些异常
和打印它一些错误信息
然后我们继续做
我们整个界面的布局
我们把我们的sp这个对象
也就是我们的滚动版面对象
放置到我们整个窗口的center
也就是中间这个位置
然后我们又构造了一个面板对象
new JPane
然后把面板对象
添加到我们整个窗口的南部区域
紧接着我们又构造一个按钮
JButton 发送
然后又构造一个文本输入区域tf
然后它的宽度是20个字符
然后一开始说我们这个
要求把输入的光标
要放在我们这个
TextField对象tf上面
所以它调用了tf.reguestFocus
获得焦点
然后这时候我们把tf这个对象
add到我们面板p当中
把我们的send
也就是我们这个按钮
也add到我们面板p当中
然后我们设置这个窗口的话
是可以退出的
然后设置可建为这个true
也就是整个窗口可显示
那这时候我们整个界面布局
基本完成
那就要马上考虑一下
这个消息处理机制
那消息处理机制的话
在整个这个例子当中
我们是只需要对按钮send
和对JTextField tf
注册它的监听器
属于ActionListener
那处理它的这些时间的对象
就叫this 就是我们当前的对象
所以可以看到
send.addActionListener
tf.addActionListener
那我们整个这构造
还没有完全结束
因为还要根据这个
isServer这个参数
来决定到底在进行
网络的初始化过程中
谁当服务端 谁当客户端
那如果是服务端的话
它就需要去构造一个Socket
然后我们Server等于空
然后Server等于
new ServerSocket
就是构造一个ServerSocket对象
然后紧接着还要构造一个
mySocket
mySocket的话它实际上是
我们Socket对象
然后怎么得到
和对应的客户端联系呢
通过下面的mySocket
等于Server.accept
那通过这个ServerSocket对象
它的accept方法
会返回一个mySocket对象
那有了这些Socket
连接构成了以后
我们就可以构造
我们的输入输出流了
那构造输入输出流目的
就是为了进行网络通讯
怎么构造呢 我们看这里
is等于new BufferedReadrr
new inputStreamReader
括弧mySocket.getinputSream
那就通过mySocket
获得它的输入流
同样的道理
通过mySocket获得它的输出流
然后在外边包上一层PrinWriter
然后最后复制一个os
那后面的话我们就会根据
这个is和os
就分别进行输入输出的这种通讯
如果不是充当服务端的话
那就意味着我们要充当客户端
那充当客户端的话
相对简单一些
那就是我们mySocket
等于newSocket IP port
也就是说我构造一个Socket对象
里面指明了我要连接的目标IP
和端口号
那拿到这个Socket对象了以后
我就可以通过Socket对象
来构造输入流和输出流
分别是通过
mySocket.getOutputStream
然后外面包了一层PrintWriter
我们就得到了os这个输出流对象
那通mySocket.getOutputStream
我们获得它的输入流
在外面包了一层InputStreamReader
然后再包了一层BufferedReadr
我们就得到了它的输入流is
那这样的话我们就构造出了这个
无论是客户端还是服务端
我们都得到它的输入流和输出流
后面就可以利用它这些流
进行通讯了
好 那这个过程是什么样的呢
我们看一下
while true就表明说
我是一个一直在循环
一直在循环
try line等于is.readLine
这个我们通过这个is
获得它的这么一个这个输入
好了 这个输入
我们实际上是基本上是要显示
因为这是从那个网络上
发过来的信息
我要把它这个相当于是聊天信息
我要把获得它的时间
给它显示出来
那我们怎么获得时间呢
Date等等new Date
这是一个日期对象
然后我们在显示这个
日期对象的时候
还可以按照一定的格式来显示
比如说我们用了一个类
SimpleDateFormat formatter
等于new SimpleDateFormat
里面是按照
年 月 日 时 分 秒来显示的
那紧接着我们根据
这个Format这个对象
调用它的Format方法
把我们当前的日期对象作为参数
然后这样的话
它就会得到一个字符串
字符串的话就是显示了
当前年月日时分秒
那我们把这个信息
就展示在我们的整个
文本区域当中 那怎么展示
因为我们定义了一个字符串s
然后它原有的内容
再加上currentTime
也就是当前的时间
再加上remoteID
也就是到底是远程
哪一个聊天的ID
再加上说说了什么话呢
然后这个话就是我们刚才
那个line里面读进来
它那从远程发过来的这些话
然后把所有这些字符串信息
都加入到原有的那s
这个字符串当中
那紧接着我们要把这个s字符串
显示到我们的文本区域上
怎么显示呢
通过ta.setText s
这样的话就把它就展示在
我们这个文本区域上面了
那这个时候你能看到效果
就相当于远程对方聊天时候
发过来一个信息
我的这一端我接收到了以后
我就把它转换成字符串
然后就添加到
我的这个文本区域上
它看起来就是像那对方
聊天过来的信息
被我显示出来了
好 我们接下来再看一下
怎么做事件处理
因为做事件处理的原因
是在于说我们本地输入的信息
要能够被捕捉到
也就是说聊天的时候
我们是通过文本框输入信息的
那到底文本框输入了啥信息呢
那我们通过我们的actionPerformed这个方法
来去获得
那在这个方法当中
它第一行代码
是date等于new Date
获得它的日期
然后通过我们刚才的类似的这个
SimpleDateFomat
formatter这个对象
然后我们就能够把这个
聊天的信息加上它的这个时间
转换一下
你看这个String currentTime
等于formatter.format date
把这个当前时间
转化成这种格式
紧接着我们把这个时间
加上我们自己这个ID
再加上说这个字符
再加上tf.getText
大家注意tf.getText
就是从我们这个文本区域里面
就文本框里面
得到我们输入的内容
然后所有这些都加到
字符串s当中
那字符串s当中紧接着
我们要把它进行显示了
因为显示到哪呢
就显示到我们整个窗口
当中的文本区域
那怎么让它显示出来呢
就是ta.setText s
那显示出来了以后
我们还有另外一个任务是什么
因为聊天嘛
我要把我自己这一方输入的信息
我要发送给对方 怎么发送
os.println
然后打印的内容是tf.getText
就要刚才文本框中输入的信息
然后os.flush 然后就输出去
然后这时候输出出去
就相当于从本地
发送给另外聊天方
他紧接着我们tf.setText为空
因为你聊天的时候
要把接收完上一条信息
发送出去之后
就要把这条信息立刻清零
紧接着tf.requestFocus
要求我们这个文本框
要能够获得焦点
以方便于我们聊天人
进一步输入他的信息
基于上面我们定好的类
我们可以把它实例化
成为两个聊天的这个客户端
一个当然要充当服务端
另外一个充当客户端
那我们看我们这个类
public class ChatServerFrame
它的主方法里面
就是这个定义的
ChatFrame cserver
然后new ChatFrame
那ChatFrame
就刚才我们定义完了这个类
我们给它参数Cat Dog
那Cat表明是自己的ID是Cat
然后远程的ID是Dog
然后那它要连接的远程服务对象
Server是127.0.0.1
端口是2009
然后true是表明
它是充当Server端
所以这是我们的
ChatServerFrame
那下面一个类是
ChatClientFrame
它的主方法里面
也是构造一个
ChatFrame这个对象
那只不过我们是让它
充当的是客户端
然后new Chat Frame
这个类的时候
他自己的名字叫Dog
远程的地方叫Cat
然后它这个要连接的这个
Server的话
这个地址是127.0.0.1
端口是2009
那它最后一个false表明
它不是充当Server
是充当的是这个cclient
那这两个程序
我们各自用一个
java虚拟机启动起来
当然应该先启动
那个Server端那个程序
然后再启动cclient这个程序
我们就可以看到
有两个图形界面
那两个图形界面以后
大家就可以拿它
来进行聊天的这个通讯
虽然说从这个界面上来说
是非常简单
甚至说是非常简陋
但是它也是揭示了
我们整个网络通信
尤其是机遇TCPIP
基于Socket通信的一种机理
这一节我们实现了
一个阿猫和阿狗聊天的程序
这个就是本节的内容
下面总结一下本章的学习内容
在本章当中
我们介绍了如何基于TCP
和Socket来实现网络编程
尤其是多客户端的编程
其次我们又学习了
基于UDP和DatagramSocket
来实现通信以及广播的机制
最后我们还学习了
如何去实现一个网络聊天程序
尤其是带界面的网络聊天程序
希望通过这些的学习
能够让大家更好的掌握
java网络的编程知识
上述就是本章的内容
-1.0 导学
--Video
-1.1 线程的基本概念
--Video
-1.1 线程的基本概念--作业
-1.2 通过Thread类创建线程
--Video
-1.2 通过Thread类创建线程--作业
-1.3 线程的休眠
--Video
-1.3 线程的休眠--作业
-1.4 Thread类详解
--Video
-1.5 通过Runnable接口创建线程
--Video
-1.5 通过Runnable接口创建线程--作业
-1.6 线程内部的数据共享
--Video
-2.0 导学
--Video
-2.1 线程同步的思路
--Video
-2.2 线程同步的实现方式—Synchronization
--Video
-2.3 线程的等待与唤醒
--Video
-2.4 后台进程
--Video
-2.5 线程的生命周期与死锁
--Video
-2.6 线程的调度
--Video
-3.0 导学
--Video
-3.1 线程安全与线程兼容与对立
--Video
-3.2 线程的安全实现-互斥同步
--Video
-3.3 线程的安全实现-非阻塞同步
--Video
-3.4 线程的安全实现-无同步方案
--Video
-3.5 锁优化
--Video
-4.0 导学
--Video
-4.1 URL对象
--Video
-4.2 URLConnection对象
--Video
-4.3 Get请求与Post请求
--Video
-4.4 Socket通信原理
--Video
-4.5 Socket通信实现
--Video
-5.0 导学
--Video
-5.1 Socket 多客户端通信实现
--Video
-5.2 数据报通信
--Video
-5.3 使用数据报进行广播通信
--Video
-5.4 网络聊天程序
--Video
-6.0 导学
--Video
-6.1 Java虚拟机概念
--Video
-6.2 Java虚拟机内存划分
--Video
-6.3 Java虚拟机类加载机制
--Video
-6.4 判断对象是否存活算法及对象引用
--Video
-6.5 分代垃圾回收
--Video
-6.6 典型的垃圾收集算法
--Video
-6.7典型的垃圾收集器
--Video
-7.0 导学
--Video
-7.1 集合框架与ArrayList
--Video
-7.2 LinkedList
--Video
-7.3 HashMap与HashTable
--Video
-7.4 TreeMap与LinkedHashMap
--Video
-7.5 HashSet
--Video
-8.0 导学
--Video
-8.1 Java反射机制
--Video
-8.2 Java静态代理
--Video
-8.3 Java动态代理
--Video
-8.4 Java 反射扩展-jvm加载类原理
--Video
-8.5 Java进阶课程总结
--Video