初始的思维
相信很多做后端开发的同学,在 github 或者其他地方阅读搜索一些开源代码,阅读它们的时候,都有见到过服务编写的多种形式,并意识到怎么不都是 HTTP 形式的服务。
比如看到 A 项目的代码,里面的请求登录
或获取用户信息
,从入口函数到返回输出都没见到熟悉的RouterPath
以及 HttpMethod
。
这很正常,我们一开始接触后端服务的时候,99%的开发者都是从 HTTP 服务开始,思维习惯于 HTTP 服务的代码阅读风格。比如下面的,就很熟悉。
router = router.append("POST","/login",func(){}).append("POST","/getUserInfo",func(){})
server.listen(":9000",router)
这种服务格式对我们来说,一目了然。这就是使用最广的 HTTP 服务。而对于 TCP 服务的直接实现就看得云里雾里。
面向自定义的 TCP 服务
然而,当一些项目做得很大的时候,它们的服务所采用的实现方式绝大多数是自定义的形式。尽管如此,自定义的层数也多截止到传输层的 TCP。
基于 TCP 协议做服务的定制化
比如下面的 TCP 服务端伪代码。
func main() {
listen = net.Listen("tcp", ":20000")
for {
conn = listen.Accept() // 建立连接
go process(conn)
}
}
func process(conn net.Conn) {
defer conn.close()
for {
var buf [128]byte
n = conn.Read(buf[:])
// if err return
recvStr := string(buf[:n])
fmt.Println("服务端收到客户端发来的数据:", recvStr)
conn.Write([]byte("Hello World"))
}
}
客户端请求的时候,怎么请求?直接就是建立 TCP 链接,然后写字节数据。
这样的一来一往,完全没有了 HTTP 服务常见的 GET
或POST
等method
,Path
也不见了。这样也能实现 Client 与 Server 的通讯。
我一般称这类服务为:TCP 直连服务
HTTP 服务本质
HTTP 全称是超文本传输协议
。属于 OSI
模型中的应用层
。而 TCP 是传输层,属于更低层的协议,HTTP 所接收的服务请求最终都会走到 TCP 中来。
既可以理解为 HTTP 是在 TCP 的基础上增加的一套通用且便捷
的数据解析规则后形式的应用层协议。这套规则就是 HTTP 报文规则
。
比如一个 HTTP 请求报文
是下面的格式:
[Method] [Url] [Version][\r\n]
[Key:] [Value][\r\n]
...
[Key:] [Value][\r\n]
[\r\n]
[Body]
----------对应于-------------
GET /userInfo HTTP/1.1
Content-Type: text/html
Content-Length: 44
Content Here ...
又由于,几乎 HTTP 服务的网络框架都支持了这么一套规则,所以这么一个报文,在传输到 TCP 端的时候,数据读取就会变成下面这个样子,我们改装下上面的的 process
函数,使得它实现 HTTP 的回复形式:
func process(conn net.Conn) {
defer conn.close()
for {
var buf [128]byte
total = conn.Read(buf[:])
// if err return
obj = httpParse(buf[:]) // 按照 Http 报文协议解析请求的数据流
if obj.metohd == "GET" && obj.url == "/userInfo" & ... {
// 以 http 报文格式回复
resp = "Hello World"
conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: {respLen}\r\n\r\n" resp))
contine
}
conn.Write([]byte("Hello World"))
}
}
上面伪代码展示了一个简单的例子。现在的 HTTP 服务框架都是基于这种形式来实现封装后给到开发者使用的。如果你想试试,你也可以封装自己的轮子,比如 HTT_Q
协议。
业界还有 FTP
、TELNET
这些应用层协议,它们和 HTTP 同级。都是基于 TCP 开发出来的。
服务的约束
如果基于 TCP 服务来实现一套自己的应用层协议。这意味着,请求的客户端也要跟随实现自己的请求框架。同时在网络中传输数据我们还要考虑安全性,整体去看就是开发成本比较高。
所以基于下面的条件限制,我们现在绝大多数服务采用 HTTP 服务,而不是 TCP 数据裸传服务。
- 协议规范定制;
- 基于规范的代码框架开发;
- 规范中安全算法的稳定及其可靠性;
- 数据的包装及其传输的效率。
对于安全这个,基于 HTTP 协议家族中的 HTTPS 就是专门解决这个问题而生的。
本文出至:学新通技术网
标签: