[Java聊天室服务器]实战之五 读写循环(服务端)

前言

学习任何一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的“多谋善断";本系列虽然涉及的是socket相关的知识,但学习之前,更想和广大程序员分享的是一种心境[Java聊天室服务器]实战之五 读写循环(服务端):学习是一个循序渐进的过程,心态应该随时调节,保持戒骄戒躁的状态。比如最近在看网易公开课MIT《算法导论》,老师提到,学习算法之前要计算机数学+离散数学+概率论等课程的知识,所以一直学不好算法的程序员不妨从基础入手,这都是中国式教育惹的祸啊!(此处省略一万字......)


原文地址:Building a Java chart server[1]

项目源码:Socket_Chat

目录

      • [Java聊天室服务器]实战之六 去除死链接(未完成)
      • [Java聊天室服务器]实战之七 客户端类(未完成)
      • [Java聊天室服务器]实战之七 读写循环(客户端)(未完成)

正文

通信协议

现在我们已经了解从哪里和客户端连接,应该谈一谈我们的通信协议


每一个客户端/服务端 系统都会有一个通信协议,它只是用于传输信息到前端和后台的格式。协议可以很简单但很难得到小块协议,或者它很标准精妙以至于已经在全世界内协会正式批准。反正,它是一个协议。


我们将要我们自己的协议,因为在Java语言中是很容易做到的,而且付出一点就可以得到已经存在的标准协议。我们的协议会非常简单。


Java语言有一套非常有用的类,称做DataInputStream 和DataOutputStream。这些类允许你读取和输出底层数据对象(比如整形和字符串)到流中,不考虑它们输出的格式。由于这些类使用相同的格式,而且格式是不会改变的,你可以肯定整数会被写入DataOutputStream,在另一方面会从DataInputStream读出。


我们的协议会是这个样子:

  • 当用户在聊天窗口输入某些事情时,他们的信息作为字符串通过DataOutputStream 传递。
  • 当客户端通过DataInputStream接收信息,它会发送相同的信息给所有用户,同样也会作为字符串通过DataOutputStream传递。
  • 用户使用DataInputStream接收信息。
协议就是这样!

—————————————————————————————————————————————————————————————————————————

什么是线程?

 Java语言的两个主要优点:网络和多线程。也不是说其他语言就不支持上面的功能 -- 它们也支持。但是Java语言的抽象可以很简洁地提供这些功能,特别对于商业语言来说。


线程一般定义为单个进程里面独立的控制线。真实的意思是说在同一时间,多线程的程序具有多线程,在其内部具有半自主活动的特点。


多线程类似于一个任务和多任务的概念,除了在一个程序中的多个线程可以共享相同的数据空间的不同。并且这样让风向数据更加直接和有效率 -- 同样变得更加容易混乱,不受控制。

—————————————————————————————————————————————————————————————————————————

循环


现在我们进入核心服务端循环 -- 这是真正聊天工作的代码,让我们看一看:

// 当构造函数调用start()的时候,会在单独的线程里
	public void run() {
		try {
			// 为通信创建DataInputStream;客户端使用DataOutputStream输出给我们
			DataInputStream din = new DataInputStream(socket.getInputStream());
			// 一直循环
			while (true) {
				// ... 读取下一条信息 ...
				String message = din.readUTF();
				// ... 输入到控制台上 ...
				System.out.println("Sending " + message);
				// ... 服务端发送它给所有的客户端
				server.sendToAll(message);
			}
		} catch (EOFException ie) {
			// 不需要错误信息
		} catch (IOException ie) {
			// 需要错误信息,输出至控制台
			ie.printStackTrace();
		} finally {
			// 因某种原因,连接会关闭,所以服务端会处理它
			server.removeConnection(socket);
		}
	}

你会注意到我们在多个地方使用了务端对象。


第一个地方时当我们调用server.sendToAll()。实际上是一个很方便的函数。我们会请求服务器列举所有连接另一面的OutputStreams,然后把这些信息写入到这些流中。但是因为这么做是很频繁,我们把所有的这么工作放到服务器这端,sendToAll()方法里面。

—————————————————————————————————————————————————————————————————————————

结束语

第二个使用服务端对象的地方会在下一节中提到。

参考文献

[1]. Building  a Java chart server

[2]. Java sockets 101以及中文系列 JAVA套接字(Socket)101

[3]. Java socket通信基本原理介绍

[Java聊天室服务器]实战之五 读写循环(服务端),布布扣,bubuko.com

[Java聊天室服务器]实战之五 读写循环(服务端)

上一篇:Java I/O


下一篇:最长公共子序列python实现