Skip to content

mapingfan/ChatApplication

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 

Repository files navigation

README

标签(空格分隔): Java Chat


文档用于记录学习Java语言过程中写的小项目,无太大的参考价值。

0.1版本

最初的版本,只是绘制出图形界面,把一个基本聊天程序所需要的组件显示出来,比如TextArea,TextField组件。这个版本比较简单,只需要用到AWT里几个相关的类就好。这个过程相当于复习了简单的Java GUI编程知识。

0.2版本

到了第二个版本,在第一代版本的基础上添加新的功能。 我们首先给按钮添加了事件。对于窗口关闭按钮,一开始点击是没有响应的,我们给他添加响应事件。添加响应事件可以回归Java中的匿名类,内部类,事件模型等基础知识。借助IDEA等开发工具,写匿名类很简单。对于内部类的使用场景得到了理解。毕竟新的技术源于需求。跟内部类一同学习的知识还有四种方法,用于访问其他类成员变量的方法,具体可以复习Java笔记。

0.3版本

第三个版本我们实现了多客户端连接到同一个服务器。这个地方可能是整个程序最难的地方。虽然现在Java技术可能都使用异步模型实现通信软件。但这个地方,为了练习多线程技术,特意使用多线程进连接管理。对于这个地方的多线程技术,需要常常回顾。对于多线程技术的使用,重点是要想清楚多线程要执行什么任务。这个地方如果能一开始就想清楚多线程专门负责管理连接,那么很简单的就可以实现。 这个地方需要经常回顾看代码,加强感觉。

0.4版本

这个版本基本就是最终版本。我们实现了多线程接受消息,实现了客户端转发。这个地方有一些技术细节需要注意。比如如何探测一个客户端退出了。

最终版

最终版会重新组织代码,对某些方法,变量的属性加以限制,力求实现的更加完美,并且回尝试回顾整个开发流程。

总结

这是我写的第一个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的基础知识。我想把这些东西内化到自己的脑海中,而不是凭记忆背诵出来。

About

Java局域网聊天

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages