主页 > 城市

Java自定义网络协议简单入门(基于Socket)

时间:2019-11-25 来源:熊猫流量小王子
Java自定义网络协议简单入门(基于Socket)

前言

了解计算机网络的同学肯定知道TCP/IP协议,TCP协议是面向字节流的协议,也就是数据是以流的形式发送的,因为没有消息边界,所以你无法知道一条消息从哪里开始,到哪里结束。常见的做法是给这些流(字节)做一些标记,在读取的时候,当读到这些标记的时候,就能区分出一条完整的消息。

这样就诞生了一些在TCP基础上的协议,我们常见的HTTP、WebScoket等。为什么我们在使用这些协议的时候,直接发送、读取就能得到一条完成的消息呢?因为这些协议本身做了消息边界的界定,在发送时按照协议的定义内部做了Encode,同理在接收时内部也做了Decoder操作。

但我们工作中作往往需要根据业务的规则,去自定义网络协议,自定义网络协议最重要的一点就是界定消息边界,然后根据消息边界来解析数据。下面,我们基于Java Socket来实现一个最简单的网络协议。

自定主网络协议

一般的网络协议主要由两部分组成:

Java自定义网络协议简单入门(基于Socket)

  • 消息头:一般根据业务情况来设计,可以有消息体长度、消息类型、业务类型、各类非业务标识等。
  • 消息体:一般就是业务数据,常见有两种划分,一种是JSON格式,一种是固定字段,因为JSON扩展性好,所以消息使用JSON封装会比较有优势。

我们接下来实现一个最简单的协议

消息头:消息体字符串的长度

消息体:一段普通的字符串

流程

  1. 客户端在标准输入中任意输入字符串
  2. 按照协议进行数据封装并发送给服务端
  3. 服务端接收到数据后,按照协议解析出数据,并重新发送回给客户端
  4. 客户端接收到数据后,同样按协议解析出数据。

实现代码

  • 服务端
Java自定义网络协议简单入门(基于Socket)

服务端代码实现

1、先读取数据流中的前两个字节,即为消息体的长度

2、根据1中的消息体长度创建数组

3、将剩余数据读入到数据,并Decoder成字符串

4、按照协议把原消息,写入到DataOutputStream中进行发送

  • 客户端

客户端发送消息:

Java自定义网络协议简单入门(基于Socket)

客户端发送代码

1、获取消息的长度,注意不是message.length,而是先转成字节数据再取数据的长度。

2、将长度和内容分别写入到DataOutputStream中,并发送。

客户端接收消息:

Java自定义网络协议简单入门(基于Socket)

客户端接收代码

1、启动接收线程接收消息

2、从Socket的InputStream中读到数据,先读取两个字节的消息体长度,再根据读出的长度创建一个同样大小的数组去读取剩余的数据。

结果

Java自定义网络协议简单入门(基于Socket)

客户端结果截图

Java自定义网络协议简单入门(基于Socket)

服务端结果截图

总结

一个最简单的自定义协议基本上是这样,实际工作中消息体一般都会是JSON格式的字符串,通过JSON解析类库解析成对应的实体结构即可,在工作中一般也不会使用原生的Socket去实现协议,一般会使用比较强大的网络框架如Netty去实现,Netty是基于Java NIO实现的一个高性能的网络框架,自带有很多实用的编码器,解码器,下次我会使用Netty去实现自定义协议,希望大家多多关注,谢谢。