标签(空格分隔): Java Chat
文档用于记录学习Java语言过程中写的小项目,无太大的参考价值。
最初的版本,只是绘制出图形界面,把一个基本聊天程序所需要的组件显示出来,比如TextArea,TextField组件。这个版本比较简单,只需要用到AWT里几个相关的类就好。这个过程相当于复习了简单的Java GUI编程知识。
到了第二个版本,在第一代版本的基础上添加新的功能。
我们首先给按钮添加了事件。对于窗口关闭按钮,一开始点击是没有响应的,我们给他添加响应事件。添加响应事件可以回归Java中的匿名类,内部类,事件模型等基础知识。借助IDEA等开发工具,写匿名类很简单。对于内部类的使用场景得到了理解。毕竟新的技术源于需求。跟内部类一同学习的知识还有四种方法,用于访问其他类成员变量的方法,具体可以复习Java笔记。
第三个版本我们实现了多客户端连接到同一个服务器。这个地方可能是整个程序最难的地方。虽然现在Java技术可能都使用异步模型实现通信软件。但这个地方,为了练习多线程技术,特意使用多线程进连接管理。对于这个地方的多线程技术,需要常常回顾。对于多线程技术的使用,重点是要想清楚多线程要执行什么任务。这个地方如果能一开始就想清楚多线程专门负责管理连接,那么很简单的就可以实现。
这个地方需要经常回顾看代码,加强感觉。
这个版本基本就是最终版本。我们实现了多线程接受消息,实现了客户端转发。这个地方有一些技术细节需要注意。比如如何探测一个客户端退出了。
最终版会重新组织代码,对某些方法,变量的属性加以限制,力求实现的更加完美,并且回尝试回顾整个开发流程。
这是我写的第一个Java项目,代码加起来不到200行,核心代码加起来估计120行左右。这个项目中,体会了调试程序,学会版本迭代开发,功能逐渐添加。
- 首先绘制出客户端的聊天界面。客户端聊天界面应该由两部分组成。消息显示区域,消息发送区域。
- 第二步,添加窗口关闭事件,添加消息发送区域响应事件。当按下回车按钮,发送区域的消息要显示到消息显示区域。
- 第三步,我们实现客户端和服务器端的通信。
- 第四步,服务器端接收客户端发送来的消息。这个地方遇到一个小问题。客户端发送消息时,代码如下:
public void actionPerformed(ActionEvent e) {
temp += (textField.getText().trim()+"\r\n");
textArea.setText(textField.getText().trim());
textField.setText("");
System.out.println(dataOutputStream);
try {
dataOutputStream.writeUTF(textField.getText().trim());
dataOutputStream.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
这个地方的逻辑实现有问题。我已经textField.setText("");然后发送数据,服务器端每次接收到都是空串,让我怀疑哪里的逻辑实现出了问题。这个地方要在修改原始数据之前就把数据发送出去。
- 第五步,实现多个客户端连接到同一个服务器上。这个地方需要用到多线程的知识。因为在最初的版本中,我们是用如下的代码控制连接的:
public void runServer() {
while (true) {
try {
acceptSocket = serverSocket.accept();
dataInputStream = new DataInputStream(acceptSocket.getInputStream());
System.out.println("A client has connected");
receiveMessage();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//其中receiveMessage()函数如下:
private void receiveMessage() {
String temp;
try {
while ((temp=dataInputStream.readUTF())!=null) {
System.out.println(temp);
}
} catch (IOException e) {
e.printStackTrace();
}
}
根据已有的知识,我们知道每次要实现连接,都需要运行一次accept函数。但是receiveMessage函数是一个while循环,并且其中的readUTF函数是阻塞式的方法。因此,这个函数是无法实现多个客户端同时连接到一个服务器上。为此,我们需要使用一个单独的线程管理连接。这个单独需要做的任务有哪些?
- 首先是接受连接,要运行accept函数。
- 其次要接收输入。
- 在已经可以接受多个客户端连接的基础上,我们需要把接受来的消息转发到其余客户端。这个时候需要写一个新的函数。由于转发消息,需要获得相应的
socket连接。所以,我们需要保存每个线程的socket连接。服务器端转发,客户端需要进行接收显示,接收也需要相应的socket连接。但是客户端由于我们每次启动有一个客户端,就相当于启动一个线程,所以接收时候可以不使用多线程。两种方法都可以。 - 完成上面的步骤,就基本实现了这个软件的主要功能。
- 从上面的步骤可以看出,开发过程是逐步迭代的,一个个功能往上加。如果一开始就设想好了整个软件的所有细节,这对新手无疑是个巨大的挑战。作为菜鸡,我选择循序渐进。
- 之所以会对这种小项目,写这么详细的文档,主要用于自己回顾复习
J2SE的基础知识。我想把这些东西内化到自己的脑海中,而不是凭记忆背诵出来。