1.概述
最近没有写想法,但本着长时间不写会生疏的说法,还是简单写一篇技术文章。这篇主要聊聊网络方面知识,涉及面广,但是不深 a。OK,话不多说,下文主要就是先介绍网络工作原理,然后从语言层面进行具体的实现分析。希望对大家有所帮助。
2.网络现状
互联网是离不开网络的(说了句废话)。比如IM、游戏、浏览器网页等场景,都需要网络的支持。网络依赖协议,没有协议是无法进行网络传输的。因为别人并不知道你发送的是什么妖魔鬼怪。
目前用的最多的就是IP协议。传输层一般是TCP和UDP。游戏场景可能用UDP多一点,毕竟TCP为数据传输可靠以及网络链路做出了很大的让步。这也是理所应当的。正是因为多种场景才会出现多个协议。如果一个TCP能解决所有问题,那有它一个就够了。应用层有个通用的HTTP协议。
3.网络工作原理
我们今天就以浏览器访问网页的用例来聊聊网络是如何连接工作的。 浏览器(就是一个软件)通过多个进程去工作。其中一个就是用来进行网络通信的进程(具体是不是这样不清楚,但大概差不多),当我们从输入框输入网站地址的并点击访问的时候,整个网络通信就开始了。
生成HTTP请求
对于请求,大家应该都不陌生,进行网络通信的时候,都需要一个对应协议的请求。浏览器在应用层使用的是HTTP协议。为什么是HTTP,为什么需要协议。一方面为了让多语言可以通信(比如浏览器一般是C++,服务器可以是JAVA或者其他)。另一方面也是为了根据需求需要一些记录。也就是每个数据包公有的部分。
比如HTTP请求第一行就是如下数据。我们可以通过方法判断什么请求,可以通过URI区分请求的资源路径等。
方法 空格 URI 空格 HTTP版本
当然,我们也可以实现自己的应用层协议满足我们的场景。虽然使用HTTP可以满足任何场景,但一些多余数据会影响网络通信性能。目前的大部分RPC调用都是自定义协议。一些游戏场景也是如此。对于应用层的开发,我们能做的可能就只有改应用层协议了。
或许有些人说可以基于UDP去改装一个传输层的协议。但这其实还是依赖UDP(比如KCP协议)。
这里所说的协议就是应用层一些。可以这么说:哪一层的协议就会在对应层进行处理。
- 如果是传输层协议TCP。那么操作系统的TCP模块收到包后,进行模块内逻辑处理完成后,砍掉TCP头部(TCP协议部分),将数据丢给应用层。
- 如果应用层协议,我们的应用层服务器收到数据包之后,会进行处理,最后将所有数据封装丢给我们去做逻辑。
一个数据包,在我们想要发出去之后,他会进行层层包装。然后转换成电信号,传输到对端。对端又会层层解包装。感觉就像是一个入栈出栈的过程。
查询解析域名
首先浏览器进程会根据输入的域名去获取对应域名的IP地址。这个过程叫做域名解析(DNS解析)。其实就是从本机配置,缓存或者DNS服务器获取域名对应的IP。当然DNS服务器也支持通过IP查域名。这是一个可逆的过程。详细的大家可以去了解域名解析过程。我们目前知道目的和结果就行。
TCP模块
构造好应用层请求数据包,并查询了目的地。浏览器进程会委托TCP模块将数据包发送出去。 这里所说的协议栈描述的就是操作系统的TCP/IP模块。因为是操作系统的模块,所以我们一般无法直接修改它的逻辑。我们能做的最多的就是通过操作系统提供的参数配置进行优化传输。这个读者可以详细了解。
图片来自 《网络是怎么连接的》
使用TCP发送数据包,需要建立连接。经过三次握手之后才能收发数据,结束之后,也是需要进行四次挥手的。 TCP模块会为应用层数据封装一个TCP头部。然后丢给IP模块。TCP建立连接的方式也是如此。相当于发一个不带应用层数据的TCP头部,并标志相应的字段告诉对端这是一个建立连接的请求包。
具体的TCP模块内容,大家可以去看看内核TCP源码。过程十分复杂(毕竟工业落地要考虑各种问题),但是大概了解应该还行。或者可以看看相关paper。
IP模块
IP模块负责的事情也比较多。因为经过IP模块处理后,网卡只需要将包传输出去即