对于初学者,或者没有接触过网络编程的程序员,会觉得网络编程涉及的知识很高深,很难,其实这是一种误解,当你的语法熟悉以后,其实基本的网络编程现在已经被实现的异常简单了。
网络通信作为互联网的技术支持,已被广泛应用在软件开发中,无论是Web,服务端,客户端还是桌面应用,都是必须掌握的一门技术。
在软件开发层面实现远程数据交换的编程技术。网络编程的本质是两个设备之间的数据交换,当然,在计算机网络中,设备主要指计算机。数据传递本身没有多大的难度,不就是把一个设备中的数据发送给另外一个设备,然后接受另外一个设备反馈的数据。
OSI参考模型,也可以叫做OSI七层模型,在学习网络编程的时候,都会接触到OSI七层模型
,我们一般使用的网络数据传输由下而上分为七层,这是一个理论的模型。分别是物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
。如下表所示:
为什么OSI要采用分层的形式?因为一个软件逻辑的实现,就是对其进行分层处理。最熟悉不过的就是MVC
,如把后台的代码会分为,数据层,表现层,业务逻辑层,还有现在的前后台分离这种,其实都是分层的一种表现形式,让每一部分的工作都变的跟加的精确和具体。
但是在项目中不会像IOS参考模型中那样分层那么细致,比较常用的可能就是TCP/IP
协议,那么说到这,什么又是TCP/IP
协议:
TCP/IP
提供点对点的链接机制,将数据应该如何封装、定址、传输、路由以及在目的地如何接收,都加以标准化。它将软件通信过程抽象化为四个抽象层,采取协议堆栈的方式,分别实现出不同通信协议。协议族下的各种协议,依其功能不同,被分别归属到这四个层次结构之中,常被视为是简化的七层OSI模型
。
通过上表中可以看出各个层级所包含的协议,可以把第一层和第二层看作为底层协议,然而在编写软件过程中很少的时候会用到这两层,因为这辆层一般用到会涉及到物理设备,例如链路、无线这些东西,很少会涉及到软件的逻辑。第三层是在软件开发过程中比较常用的,比如TCP,UDP之后会详细介绍。应用层会更加的熟悉,在做远程登录,数据传输时会频繁的使用到。
DNS
解析的过程就是寻找哪台机器上有你需要资源的过程。当你在浏览器中输入一个地址时,例如www.google.com
,其实不是百度网站真正意义上的地址。互联网上每一台计算机的唯一标识是它的IP
地址,但是IP
地址并不方便记忆。用户更喜欢用方便记忆的网址去寻找互联网上的其它计算机,也就是上面提到的百度的网址。所以互联网设计者需要在用户的方便性与可用性方面做一个权衡,这个权衡就是一个网址到IP地址的转换,这个过程就是DNS
解析。它实际上充当了一个翻译的角色,实现了网址到IP
地址的转换。网址到IP
地址转换的过程是如何进行的?
首先在本地域名服务器中查询IP
地址,如果没有找到的情况下,本地域名服务器会向根域名服务器发送一个请求,如果根域名服务器也不存在该域名时,本地域名会向com
顶级域名服务器发送一个请求,依次类推下去。直到最后本地域名服务器得到google
的IP
地址并把它缓存到本地,供下次查询使用。从上述过程中,可以看出网址的解析是一个从右向左的过程:com -> google.com -> www.google.com
。但是你是否发现少了点什么,根域名服务器的解析过程呢?事实上,真正的网址是www.google.com
.,并不是我多打了一个.,这个.对应的就是根域名服务器,默认情况下所有的网址的最后一位都是.,既然是默认情况下,为了方便用户,通常都会省略,浏览器在请求DNS的时候会自动加上,所有网址真正的解析过程为:. -> .com -> google.com. -> www.google.com
。
- 浏览器缓存 - 当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的IP地址(若曾经访问过该域名且没有清空缓存便存在);
- 系统缓存 - 当浏览器缓存中无域名对应IP则会自动检查用户计算机系统Hosts文件DNS缓存是否有该域名对应IP;
- 路由器缓存 - 当浏览器及系统缓存中均无域名对应IP则进入路由器缓存中检查,以上三步均为客服端的DNS缓存;
- ISP(互联网服务提供商)DNS缓存 - 当在用户客服端查找不到域名对应IP地址,则将进入ISP DNS缓存中进行查询。比如你用的是电信的网络,则会进入电信的DNS缓存服务器中进行查找;
- 根域名服务器 - 当以上均未完成,则进入根服务器进行查询。全球仅有13台根域名服务器,1个主根域名服务器,其余12为辅根域名服务器。根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器IP告诉本地DNS服务器;
- 顶级域名服务器 - 顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的IP地址告诉本地DNS服务器;
- 主域名服务器 - 主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,并重复该步骤直至找到正确纪录;
- 保存结果至缓存 - 本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器建立链接。
HTTP
协议是使用TCP
作为其传输层协议的,当TCP
出现瓶颈时,HTTP
也会受到影响。我不知道把HTTPS
放在这个部分是否合适,但是放在这里好像又说的过去。HTTP
报文是包裹在TCP
报文中发送的,服务器端收到TCP
报文时会解包提取出HTTP
报文。但是这个过程中存在一定的风险,HTTP
报文是明文,如果中间被截取的话会存在一些信息泄露的风险。那么在进入TCP
报文之前对HTTP
做一次加密就可以解决这个问题了。HTTPS
协议的本质就是HTTP+SSL(orTLS)
。在HTTP
报文进入TCP
报文之前,先使用SSL
对HTTP
报文进行加密。从网络的层级结构看它位于HTTP
协议与TCP
协议之间。
原理:Net模块提供一个异步API能够创建基于流的TCP服务器,客户端与服务端简历连接后,服务器可以获得一个全双工Socket对象,服务器可以保存Socket对象列表,在接收某客户端消息时,推送给客户端。
dome
服务端:
const net = require("net");
const chatServer = net.createServer();
const clientList = [];
chatServer.on("connection",client => {
client.write("Hi!\n");
clientList.push(client);
client.on("data",data => {
console.log("receive:",data.toString());
clientList.forEach(v => {
v.write(data);
})
})
});
chatServer.listen(9000);
TCP特性
- TCP 提供一种面向连接的、可靠的字节流服务在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP
- TCP使用校验和,确认和重传机制来保证可靠传输
- TCP给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
- TCP使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
TCP并不能保证数据一定会被对方接收到,因为这是不可能的。TCP能够做到的是,如果有可能,就把数据递送到接收方,否则就(通过放弃重传并且中断连接这一手段)通知用户。因此准确说 TCP 也不是 100% 可靠的协议,它所能提供的是数据的可靠递送或故障的可靠通知。
三次握手与四次挥手
所谓三次握手(Three-way Handshake
),是指建立一个TCP
连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立TCP
连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在socket
编程中,客户端执行connect()
时。将触发三次握手。
TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake
),也叫做改进的三次握手。客户端或服务器均可主动发起挥手动作,在socket
编程中,任何一方执行close()
操作即可产生挥手操作。
TCP断开连接时需要四次握手,为什么需要4次呢?这是由于TCP半关闭的性质造成的。所谓半关闭,就是可以发送数据,却不能接收数据或只能接收数据,不能发送数据。
说到这里就是老生常谈的话题了,作为一个前端码农来讲,在面试过程中的是时候这个问题已经被问烂了,基本每次面试都会被问到。
其实这部分又可以称为前端工程师眼中的HTTP
,它主要发生在客户端。发送HTTP
请求的过程就是构建HTTP
请求报文并通过TCP
协议中发送到服务器指定端口(HTTP协议80/8080
,HTTPS协议443
)。HTTP请求报文是由三部分组成: 请求行, 请求报头和请求正文。
特性:
- HTTP 协议构建于 TCP/IP 协议之上,是一个应用层协议,默认端口号是 80
- HTTP 是无连接无状态的
请求报文
HTTP
协议是以ASCII
码传输,建立在TCP/IP
协议之上的应用层规范。规范把HTTP
请求分为三个部分:状态行、请求头、消息主体。
HTTP 定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE
。URL
全称是资源描述符,我们可以这样认为:一个URL
地址,它用于描述一个网络上的资源,而 HTTP
中的GET,POST,PUT,DELETE
就对应着对这个资源的查,增,改,删4个操作。
- GET: 用于请求访问已经被URI(统一资源标识符)识别的资源,可以通过URL传参给服务器。
- POST:用于传输信息给服务器,主要功能与GET方法类似,但一般推荐使用POST方式。
- PUT: 传输文件,报文主体中包含文件内容,保存到对应URI位置。
- HEAD: 获得报文首部,与GET方法类似,只是不返回报文主体,一般用于验证URI是否有效。
- DELETE:删除文件,与PUT方法相反,删除对应URI位置的文件。
- OPTIONS:查询相应URI支持的HTTP方法。
所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET
请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。
GET方法与POST方法的区别
- GET可提交的数据量受到URL长度的限制,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制
- 理论上讲,POST是没有大小限制的,HTTP协议规范也没有进行大小限制,出于安全考虑,服务器软件在实现时会做一定限制
网络编程就是使用IP地址,或域名,和端口连接到另一台计算机上对应的程序,按照规定的协议(数据格式)来交换数据,实际编程中建立连接和发送、接收数据在语言级已经实现,做的更多的工作是设计协议,以及编写生成和解析数据的代码罢了,然后把数据转换成逻辑的结构显示或控制逻辑即可。
对于初学者,或者没有接触过网络编程的程序员,会觉得网络编程涉及的知识很高深,很难,其实这是一种误解,当你的语法熟悉以后,其实基本的网络编程现在已经被实现的异常简单了。