「这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战」
一、什么是协议?
在计算机网络与信息通信领域里,人们经常提及“协议”一词。互联网中常用的具有代表性的协议有IP、TCP、HTTP等。
简单来说,协议就是计算机与计算机之间通过网络实现通信时事先达成的一种“约定”。这种“约定”使那些由不同厂商的设备、不同的CPU以及不同的操作系统组成的计算机之间,只要遵循相同的协议就能够实现通信。
二、协议的必要性
通常,我们发送一封电子邮件、访问某个主页获取信息时察觉不到协议的存在,只有在我们重新配置计算机的网络连接、修改网络设置时才有可能涉及协议。
这就好比两个人使用不同国家的语言说话,怎么也无法相互理解。也可以比喻成没有断句的话,有多种不同的解释,双方可能会产生分歧。协议可以分为很多种,每一种协议都明确地界定了它的行为规范。两台计算机之间必须能够支持相同的协议,并遵循相同协议进行处理,这样才能实现相互通信。
TCP/IP 中消息传输基于流的方式,没有边界。
协议的目的就是划定消息的边界,制定通信双方要共同遵守的通信规则。
三、常见协议示例
3.1 redis协议
比如我们要发送消息给redis,需要遵从其协议。
比如我们要发送set key value 形式的命令,则我们首先要发送整个命令的长度,然后分别发送命令每个位置的长度,如下所示:
1 | arduino复制代码set name Tom |
则需要按照如下的协议发送:
1 | swift复制代码*3 //命令长度 |
我们使用如下代码连接redis并发送上面的内容:
创建一个客户端,连接本地redis:
1 | scss复制代码public class RedisProtocol { |
验证:
1 | arduino复制代码127.0.0.1:0>get name |
3.2 http协议
下面我们演示下netty当中解析http请求的示例代码。因为http协议我们自己实现太过复杂,所以我们直接使用netty提供的http编解码器:HttpServerCodec:
1 | scala复制代码public final class HttpServerCodec extends CombinedChannelDuplexHandler<HttpRequestDecoder, HttpResponseEncoder> implements SourceCodec |
如上图所示,我们发现这个类继承自CombinedChannelDuplexHandler,同时实现了编码和解码的功能。
下面我们提供个一个服务端代码,通过浏览器访问,看看最终能收到浏览器请求内容是什么样的:
1 | scss复制代码public class HttpProtocolServer { |
浏览器访问http://localhost:8080/index.html,得到如下结果:
1 | makefile复制代码DefaultHttpRequest(decodeResult: success, version: HTTP/1.1) |
分析如上内容,发现得到了很多http请求的参数内容,以及共接收到两个类型的类,分别是:DefaultHttpRequest 和 LastHttpContent,也就是说,http请求会给我们两部分的内容,分别是请求和请求体,这里无论是get还是post,都是如此。
所以,当我们想要处理一个http请求的话,需要对这两个请求进行判断去分别处理:
1 | java复制代码if (msg instanceof HttpRequest){ |
也可以使用netty提供的SimpleChannelInboundHandler的针对单一类型的入站处理器去处理请求:
1 | typescript复制代码 nioSocketChannel.pipeline().addLast(new SimpleChannelInboundHandler<HttpRequest>() { |
处理处理请求,一个正常的http请求还需要返回响应,我们用DefaultFullHttpResponse最为响应。这个类需要需要指定请求协议的version,以及请求的状态。
除此之外,我们给请求增加上响应内容:Hello World!
完整代码如下所示:
1 | scss复制代码public class HttpProtocolServer { |
浏览器请求http://localhost:8080/index.html,查看结果:
1 | bash复制代码/index.html |
本文转载自: 掘金