九、网络协议和网络编程

1.TCP建立连接的过程。

  在谈及TCP建立连接和释放连接过程,先来简单认识一下TCP报文段首部格式的的几个名词(这里只是简单说明,具体请查看相关教程)

    序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;序列号seq就是这个报文段中的第一个字节的数据编号
    确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;序列号表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。
    确认ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效
    同步SYN:连接建立时用于同步序号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。
    终止FIN:用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接
    PS:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。
一、TCP建立连接三次握手(简单就是:请求,两次确认,连接。)


(1)、三次握手的过程
   1)主机A向主机B发送TCP连接请求数据包,其中包含主机A的初始序列号seq(A)=x。(其中报文中同步标志位SYN=1,ACK=0,表示这是一个TCP连接请求数据报文;序号seq=x,表明传输数据时的第一个数据字节的序号是x);
   2)主机B收到请求后,会发回连接确认数据包。(其中确认报文段中,标识位SYN=1,ACK=1,表示这是一个TCP连接响应数据报文,并含主机B的初始序列号seq(B)=y,以及主机B对主机A初始序列号的确认号ack(B)=seq(A)+1=x+1
   3)第三次,主机A收到主机B的确认报文后,还需作出确认,即发送一个序列号seq(A)=x+1;确认号为ack(A)=y+1的报文;

(2)为什么需要第三次握手?
     还要再发送一次确认是为了,防止已失效的连接请求报文段突然又传到了B,因而产生错误。
     正常情况下:A发出连接请求,但因为丢失了,故而不能收到B的确认。于是A重新发出请求,然后收到确认,建立连接,数据传输完毕后,释放连接,A发了2个,一个丢掉,一个到达,没有“已失效的报文段”
     但是,某种情况下,A的第一个在某个节点滞留了,延误到达,本来这是一个早已失效的报文段,但是在A发送第二个,并且得到B的回应,建立了连接以后,这个报文段竟然到达了,于是B就认为,A又发送了一个新的请求,于是发送确认报文段,同意建立连接,假若没有三次的握手,那么这个连接就建立起来了(有一个请求和一个回应),此时,A收到B的确认,但A知道自己并没有发送建立连接的请求,因为不会理睬B的这个确认,于是呢,A也不会发送任何数据,而B呢却以为新的连接建立了起来,一直等待A发送数据给自己,此时B的资源就被白白浪费了。但是采用三次握手的话,A就不发送确认,那么B由于收不到确认,也就知道并没有要求建立连接。
     简而言之:第三次握手,主机A发送一次确认是为了防止:如果客户端迟迟没有收到服务器返回的确认报文,这时他会放弃连接,重新启动一条连接请求;但问题是:服务器不知客户端没收到,所以他会收到两个连接请求,白白浪费了一条连接开销。
原文链接

2.TCP断开连接的过程。

(1)四次握手过程
  假设主机A为客户端,主机B为服务器,其释放TCP连接的过程如下:
    1) 关闭客户端到服务器的连接:首先客户端A发送一个FIN,用来关闭客户到服务器的数据传送,然后等待服务器的确认。其中终止标志位FIN=1,序列号seq=u
   2) 服务器收到这个FIN,它发回一个ACK,确认号ack为收到的序号加1。
   3) 关闭服务器到客户端的连接:也是发送一个FIN给客户端。
   4) 客户段收到FIN后,并发回一个ACK报文确认,并将确认序号seq设置为收到序号加1。
     首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

     主机A发送FIN后,进入终止等待状态, 服务器B收到主机A连接释放报文段后,就立即给主机A发送确认,然后服务器B就进入close-wait状态,此时TCP服务器进程就通知高层应用进程,因而从A到B的连接就释放了。此时是“半关闭”状态。即A不可以发送给B,但是B可以发送给A
  此时,若B没有数据报要发送给A了,其应用进程就通知TCP释放连接,然后发送给A连接释放报文段,并等待确认。A发送确认后,进入time-wait,注意,此时TCP连接还没有释放掉,然后经过时间等待计时器设置的2MSL后,A才进入到close状态。

(2)为什么要等待2MSL呢?
    MSL即Maximum Segment Lifetime,也就是最大报文生存时间,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。引用《TCP/IP详解》中的话:“它(MSL)是任何报文段被丢弃前在网络内的最长时间”。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。
    TCP的TIME_WAIT状态需要等待2MSL,当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。
    概括原因如下:
    ①、为了保证A发送的最后一个ACK报文段能够到达B。即最后这个确认报文段很有可能丢失,那么B会超时重传,然后A再一次确认,同时启动2MSL计时器,如此下去。如果没有等待时间,发送完确认报文段就立即释放连接的话,B就无法重传了(连接已被释放,任何数据都不能出传了),因而也就收不到确认,就无法按照步骤进入CLOSE状态,即必须收到确认才能close。
    ②、防止“已失效的连接请求报文段”出现在连接中。经过2MSL,那些在这个连接持续的时间内,产生的所有报文段就可以都从网络中消失。即在这个连接释放的过程中会有一些无效的报文段滞留在楼阁结点,但是呢,经过2MSL这些无效报文段就肯定可以发送到目的地,不会滞留在网络中。这样的话,在下一个连接中就不会出现上一个连接遗留下来的请求报文段了。
可以看出:B结束TCP连接的时间比A早一点,因为B收到确认就断开连接了,而A还得等待2MSL.

(3)为什么TCP释放连接需要四次?
      TCP建立连接要进行三次握手,而断开连接要进行四次。这是由于TCP的半关闭造成的。因为TCP连接是全双工的(即数据可在两个方向上同时传递)所以进行关闭时每个方向上都要单独进行关闭。这个单方向的关闭就叫半关闭。当一方完成它的数据发送任务,就发送一个FIN来向另一方通告将要终止这个方向的连接。
     注意:
     1)发送了FIN只是表示这端不能继续发送数据(应用层不能再调用send发送),但是还可以接收数据。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据,比如:如主机A收到主机B的FIN断开TCP连接请求,只是表示主机B已经发送完数据,主机A收到FIN后作出应答,并终止这个方向的数据传输,此时处于半关闭状态。但是主机A仍然可以发送数据的,只有当主机A发送完数据并发送FIN给主机B时,主机B才停止这个方向的数据传输,并关闭TCP连接。
     2)在很多时候,TCP连接的断开都会由TCP层自动进行,例如你CTRL+C终止你的程序,TCP连接依然会正常关闭,你可以写代码试试。

3.浏览器发生302跳转背后的逻辑?

简介

302重定向是暂时的重定向,搜索引擎会抓取新的内容而保存旧的网址。由于效劳器前往302代码,搜索引擎以为新的网址只是暂时的。301重定向是永久的重定向  ,搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址。

301是说访问的资源已经永久删除啦,客户端要根据新的URI访问重定向;而302的意思就是说访问的资源可能暂时先用location的URI访问,但旧资源还在的,下次你再来访问的时候可能就不用重定向了。图片源于网络

public void doGet(HttpServletRequest request, HttpServletResponse response)  
        throws ServletException, IOException {  
    //请求重定向的例子  
    response.setStatus(301); 
    response.setHeader("Location", "http://127.0.0.1/login.htm");
}

网址劫持
302重定向和网址劫持(URL hijacking)有什么关系呢?这要从搜索引擎如何处理302转向说起。从定义来说,从网址A做一个302重定向到网址B时,主机服务器的隐含意思是网址A随时有可能改主意,重新显示本身的内容或转向其他的地方。大部分的搜索引擎在大部分情况下,当收到302重定向时,一般只要去抓取目标网址就可以了,也就是说网址B。
实际上如果搜索引擎在遇到302转向时,百分之百的都抓取目标网址B的话,就不用担心网址URL劫持了。问题就在于,有的时候搜索引擎,尤其是Google,并不能总是抓取目标网址。为什么呢?比如说,有的时候A网址很短,但是它做了一个302重定向到B网址,而B网址是一个很长的乱七八糟的URL网址,甚至还有可能包含一些问号之类的参数。很自然的,A网址更加用户友好,而B网址既难看,又不用户友好。这时Google很有可能会仍然显示网址A。
由于搜索引擎排名算法只是程序而不是人,在遇到302重定向的时候,并不能像人一样的去准确判定哪一个网址更适当,这就造成了网址URL劫持的可能性。也就是说,一个不道德的人在他自己的网址A做一个302重定向到你的网址B,出于某种原因, Google搜索结果所显示的仍然是网址A,但是所用的网页内容却是你的网址B上的内容,这种情况就叫做网址URL劫持。你辛辛苦苦所写的内容就这样被别人偷走了。

http状态码分类

preview

  • 200 OK 客户端请求成功
  • 301 Moved Permanently 请求永久重定向
  • 302 Moved Temporarily 请求临时重定向
  • 304 Not Modified 文件未修改,可以直接使用缓存的文件。
  • 400 Bad Request 由于客户端请求有语法错误,不能被服务器所理解。
  • 401 Unauthorized 请求未经授权。这个状态代码必须和WWW-Authenticate报头域一起使用
  • 403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因
  • 404 Not Found 请求的资源不存在,例如,输入了错误的URL
  • 500 Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求。
  • 503 Service Unavailable 服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。

4.HTTP协议的交互流程。HTTP和HTTPS的差异,SSL的交互流程?

HTTP协议是建立在TCP协议之上的一种应用。TCP是传输层,而http是应用层。TCP就是单纯建立连接,不涉及任何我们需要请求的实际数据,简单的传输。http是用来收发数据,即实际应用上来的。

(1)C发送一个HTTP请求给S,S收到了这个http请求,然后返回给Chttp响应,然后C的中间件或者说浏览器把这些数据渲染成为了网页,展示在用户面前。

(2)HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

(3)HTTP请求头部的 Content-Type 字段

1. GET 请求

GET 请求不存在请求实体部分,键值对参数放置在 URL 尾部,因此请求头不需要设置 Content-Type 字段

非 ASCII 码会自动进行编码转换,例如发送请求:www.bilibili.com?hehe=你的我的

GET /?hehe=%E4%BD%A0%E7%9A%84%E6%88%91%E7%9A%84 HTTP/1.1
Host: www.bilibili.com

2. POST 请求
第一类:raw 原始类型,可以上传任意格式的文本,比如 text、json、xml、html(中文不进行编码)

①text 请求

POST / HTTP/1.1
Host: www.bilibili.com
Content-Type: text/plain
Content-Length: 44

ALARM=hellowww&&adzdzd12323...22你的我的

②json 请求

POST / HTTP/1.1
Host: www.bilibili.com
Content-Type: application/json
Content-Length: 44

ALARM=hellowww&&adzdzd12323...22你的我的

③html 请求

POST / HTTP/1.1
Host: www.bilibili.com
Content-Type: text/html
Content-Length: 44

ALARM=hellowww&&adzdzd12323...22你的我的

第二类:application/x-www-form-urlencoded,会将表单内的数据转换拼接成 key-value 对(非 ASCII 码进行编码)

发送 POST 请求,参数为:aaa=aaa,bbb=你的我的

POST / HTTP/1.1
Host: www.bilibili.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 48

aaa=aaa&bbb=%E4%BD%A0%E7%9A%84%E6%88%91%E7%9A%84

从这里可以看出,application/x-www-form-urlencoded 对非 ASCII 的编码方式与 GET 请求参数的编码方式和格式都是一样的

值得一提的是,POST 请求的编码格式是可以人工干预的:在 form 表单所在的 html 文件里如果有段 ,那么 post 就会用此处指定的编码方式编码,JSP 也有类似的声明方式;开发人员可以用此来指定 POST 请求的编码格式

第三类:multipart/form-data,将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件

发送 POST 请求,参数为:aaa=aaa,bbb=你的我的啊啊啊,file=图片

POST / HTTP/1.1
Host: www.bilibili.com
Content-Type: multipart/form-data;boundary=------FormBoundary15e896376d1
Content-Length: 19532

------FormBoundary15e896376d1
Content-Disposition: form-data; name="aaa"

aaa
------FormBoundary15e896376d1
Content-Disposition: form-data; name="bbb"

你的我的啊啊啊
------FormBoundary15e896376d1
Content-Disposition: form-data; name="file"; filename="cat-icon.png"
Content-Type: image/png

[message-part-body; type:image/png, size:19201 bytes]
------FormBoundary15e896376d1--

原文链接:https://blog.csdn.net/pomer_huang/article/details/79495346

(3)SSL(安全套接层)

不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文传播,带来了三大风险。

(1) 窃听风险(eavesdropping):第三方可以获知通信内容。

(2) 篡改风险(tampering):第三方可以修改通信内容。

(3) 冒充风险(pretending):第三方可以冒充他人身份参与通信。

SSL/TLS协议是为了解决这三大风险而设计的,希望达到:

(1) 所有信息都是加密传播,第三方无法窃听。

(2) 具有校验机制,一旦被篡改,通信双方会立刻发现。

(3) 配备身份证书,防止身份被冒充。

TLS 1.0通常被标示为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3。

SSL/TLS协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。

(1)如何保证公钥不被篡改?

解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。

(2)公钥加密计算量太大,如何减少耗用的时间?

解决方法:每一次对话(session),客户端和服务器端都生成一个"对话密钥"(session key),用它来加密信息。由于"对话密钥"是对称加密,所以运算速度非常快,而服务器公钥只用于加密"对话密钥"本身,这样就减少了加密运算的消耗时间。

因此,SSL/TLS协议的基本过程是这样的:

(1) 客户端向服务器端索要并验证公钥。

(2) 双方协商生成"对话密钥"。

(3) 双方采用"对话密钥"进行加密通信。

上面过程的前两步,又称为"握手阶段"(handshake)。

"握手阶段"涉及四次通信,我们一个个来看。需要注意的是,"握手阶段"的所有通信都是明文的。

4.1 客户端发出请求(ClientHello)

首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做ClientHello请求。

在这一步,客户端主要向服务器提供以下信息。

(1) 支持的协议版本,比如TLS 1.0版。

(2) 一个客户端生成的随机数,稍后用于生成"对话密钥"。

(3) 支持的加密方法,比如RSA公钥加密。

(4) 支持的压缩方法。

这里需要注意的是,客户端发送的信息之中不包括服务器的域名。也就是说,理论上服务器只能包含一个网站,否则会分不清应该向客户端提供哪一个网站的数字证书。这就是为什么通常一台服务器只能有一张数字证书的原因。

对于虚拟主机的用户来说,这当然很不方便。2006年,TLS协议加入了一个Server Name Indication扩展,允许客户端向服务器提供它所请求的域名。

4.2 服务器回应(SeverHello)

服务器收到客户端请求后,向客户端发出回应,这叫做SeverHello。服务器的回应包含以下内容。

(1) 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。

(2) 一个服务器生成的随机数,稍后用于生成"对话密钥"。

(3) 确认使用的加密方法,比如RSA公钥加密。

(4) 服务器证书。

除了上面这些信息,如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供"客户端证书"。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。

4.3 客户端回应

客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。

如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息。

(1) 一个随机数。该随机数用服务器公钥加密,防止被窃听。

(2) 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。

(3) 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。

上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称"pre-master key"。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。

至于为什么一定要用三个随机数,来生成"会话密钥",dog250解释得很好:

"不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。

对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。

pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。"

此外,如果前一步,服务器要求客户端证书,客户端会在这一步发送证书及相关信息。

4.4 服务器的最后回应

服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的"会话密钥"。然后,向客户端最后发送下面信息。

(1)编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。

(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。

至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。

https://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

5.Rest和Http什么关系? 大家都说Rest很轻量,你对Rest风格如何理解?

(1)REST 实际上只是一种设计风格,它并不是标准。
链接:https://www.zhihu.com/question/28557115/answer/47846156

1、REST 是面向资源的,这个概念非常重要,而资源是通过 URI 进行暴露。
URI 的设计只要负责把资源通过合理方式暴露出来就可以了。对资源的操作与它无关,操作是通过 HTTP动词来体现,所以REST 通过 URI 暴露资源时,会强调不要在 URI 中出现动词。

比如:左边是错误的设计,而右边是正确的

GET /rest/api/getDogs --> GET /rest/api/dogs 获取所有小狗狗 
GET /rest/api/addDogs --> POST /rest/api/dogs 添加一个小狗狗 
GET /rest/api/editDogs/:dog_id --> PUT /rest/api/dogs/:dog_id 修改一个小狗狗 
GET /rest/api/deleteDogs/:dog_id --> DELETE /rest/api/dogs/:dog_id 删除一个小狗狗 

左边的这种设计,很明显不符合REST风格,上面已经说了,URI 只负责准确无误的暴露资源,而 getDogs/addDogs...已经包含了对资源的操作,这是不对的。相反右边却满足了,它的操作是使用标准的HTTP动词来体现。

2、REST很好地利用了HTTP本身就有的一些特征,如HTTP动词、HTTP状态码、HTTP报头等等
REST API 是基于 HTTP的,所以你的API应该去使用 HTTP的一些标准。这样所有的HTTP客户端(如浏览器)才能够直接理解你的API(当然还有其他好处,如利于缓存等等)。REST 实际上也非常强调应该利用好 HTTP本来就有的特征,而不是只把 HTTP当成一个传输层这么简单了。

HTTP动词

GET     获取一个资源 
POST    添加一个资源 
PUT     修改一个资源 
DELETE  删除一个资源 

实际上,这四个动词实际上就对应着增删改查四个操作,这就利用了HTTP动词来表示对资源的操作。

HTTP状态码

200 OK 
400 Bad Request 
500 Internal Server Error

在 APP 与 API 的交互当中,其结果无非就三种状态:

  • 所有事情都按预期正确执行完毕 - 成功
  • APP 发生了一些错误 – 客户端错误
  • API 发生了一些错误 – 服务器端错误

这三种状态与上面的状态码是一一对应的。

HTTP报头

Authorization 认证报头 
Cache-Control 缓存报头 
Cnotent-Type  消息体类型报头 
......

报头还有很多,不一一列举。HTTP报头是描述HTTP请求或响应的元数据,它的作用是客户端 与 服务器端进行相互通信时,告诉对方应该如何处理本次请求。

3、超媒体
老实说,这个词汇我到目前还有没搞得全懂。那也说说自己的理解吧,不一定准确哦,有错误希望指出。
”超媒体“ 你没听说过没关系,”超链接“ 你一定不会陌生。简单来说,”超链接“ 是实现超媒体中的一种方式。”超媒体“希望达到一种就是说在 REST API 中把所有资源给链接起来。它就犹如你打开一个网站的首页,你难道看到的只有首页吗?NO !, 不是的,你可以通过首页查看商品、查看文章、查看论坛。”超媒体“ 就是做这个事情,它利用 API 把所有资源的关系给链接起来了,你看到不会只是一个独立的资源,而是关系网中的一个资源。
”超媒体“ 有点高大上了,老实说,就算你够牛X,写出了一个非常棒的符合”超媒体“的REST API,你的用户即开发者,也不一定能够接受你这种高大上的设计。当然,我相信未来也许可以普及了。

简单理解为:

看Url就知道要什么
看http method就知道干什么
看http status code就知道结果如何

(2)特点

  • 客户-服务器(Client-Server),提供服务的服务器和使用服务的客户需要被隔离对待。
  • 无状态(Stateless),来自客户的每一个请求必须包含服务器处理该请求所需的所有信息。换句话说,服务器端不能存储来自某个客户的某个请求中的信息,并在该客户的其他请求中使用。
  • 可缓存(Cachable),服务器必须让客户知道请求是否可以被缓存。(Ross:更详细解释请参考 理解本真的REST架构风格 以及 StackOverflow 的这个问题 中对缓存的解释。)
  • 分层系统(Layered System),服务器和客户之间的通信必须被这样标准化:允许服务器和客户之间的中间层(Ross:代理,网关等)可以代替服务器对客户的请求进行回应,而且这些对客户来说不需要特别支持。
  • 统一接口(Uniform Interface),客户和服务器之间通信的方法必须是统一化的。(Ross:GET,POST,PUT.DELETE, etc)
  • 支持按需代码(Code-On-Demand,可选),服务器可以提供一些代码或者脚本(Ross:Javascrpt,flash,etc)并在客户的运行环境中执行。这条准则是这些准则中唯一不必必须满足的一条。(Ross:比如客户可以在客户端下载脚本生成密码访问服务器。)

HTTP API是Restful API的实现和表现,Restful API是HTTP API的基础,提供了标准接口。

(2)REST 目前作为三种 Web 服务之一,其他两种为 RPC 和 SOAP。

首先,了解一下REST流行之前Web客户端是如何访问服务器接口的?
早期在移动端没有流行之前,Web API的概念还非常的弱,当时是网站盛行的年代,基本遵循着后台-前端的模型。后台产生数据,然后通过“模板”的形式将数据绑定到前端HTML代码里(渲染)。如下图所示:

那么这里就有一个“域”的概念,JavaScript只能访问同一个域的服务器。比如我们将一个站点部署在A这个域名http://www.a.com下,那么这个站点的前端JavaScript只能访问域名为http://www.a.com的服务端。如果我们需要访问非A站点的其他“服务”怎么办?看看下图:

在当时通用的做法是使用SOAP,Simple Object Access Protocol,简单对象协议,它使用XML作为数据的描述。我们看看使用SOAP的解决方案:

JavaScript是不能直接访问SOAP服务的,需要首先访问自己的网站后台,再有网站后台访问SOAP服务。而且不同语言的网站后台,方位SOAP服务都需要有首先生成自己特定语言的“代理类”,Java有Java的、C#有C#的,这相当的繁琐与不好理解。这个时候我们的思考点来了,网站的后台对我来说意义是什么? 我为什么不能直接访问服务?为什么我不能把网站里的业务代码也提取成服务,最后变成以下的理想情况:

网站的后台几乎是个“壳子”,只负责网站本身的HTML页面、CSS、JavaScript文件等静态页面。而业务逻辑,交给服务来提供就好了。这样做的最大的好处是,业务变得独立了,可以被多个“网站”来共享访问了。有没有觉得挺熟悉?这个模式就是现在VUE、AngularJS等框架做的单页面应用程序。但是,在当时这种模式并不流行。我在很多年前就尝试这样的思维来构建Web,但是由于没有现在VUE、AngularJS等强大的SPA框架支持,效果并不好。但,我相信这种简洁的模式是Web的未来。我一向崇尚简洁,当年丢掉Flex、Silverlight、http://ASP.Net WebForm,独独选择JavaScript就是因为其他几个封装太多。

很多人认为模板引擎就是很好的前后端分离,可我不这么认为,SPA才是真正的前后端分离,他们之间使用AJax通信,前端就是最简单的HTML,前端开发人员一行服务器代码都看不到,这才是真的和语言无关,才是真正的前后端分离。

REST协议是面向资源的

假如要管理一些用户,那么将用户看作是一种资源:get /users/{userId} 获取userId对应的user信息

SOAP(简单对象访问协议(Simple Object Access Protocol))是面向服务的

还是管理用户,将对用户的操作看成服务:post /users/getUser

RPC(远程过程调用(remote procedure call))

程过程调用逐渐被SOAP取代

6.TCP的滑动窗口协议有什么用?讲讲原理。

https://blog.csdn.net/wdscq1234/article/details/52444277

7.HTTP协议都有哪些方法?

方法 说明
GET GET请求会显示请求指定的资源。一般来说GET方法应该只用于数据的读取,而不应当用于会产生副作用的非幂等的操作中。它期望的应该是而且应该是安全的和幂等的。这里的安全指的是,请求不会影响到资源的状态。
HEAD HEAD方法与GET方法一样,都是向服务器发出指定资源的请求。但是,服务器在响应HEAD请求时不会回传资源的内容部分,即:响应主体。这样,我们可以不传输全部内容的情况下,就可以获取服务器的响应头信息。HEAD方法常被用于客户端查看服务器的性能。
POST POST请求会 向指定资源提交数据,请求服务器进行处理,如:表单数据提交、文件上传等,请求数据会被包含在请求体中。POST方法是非幂等的方法,因为这个请求可能会创建新的资源或/和修改现有资源。
PUT PUT请求会身向指定资源位置上传其最新内容,PUT方法是幂等的方法。通过该方法客户端可以将指定资源的最新数据传送给服务器取代指定的资源的内容。
DELETE DELETE请求用于请求服务器删除所请求URI(统一资源标识符,Uniform Resource Identifier)所标识的资源。DELETE请求后指定资源会被删除,DELETE方法也是幂等的。
CONNECT CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信。
OPTIONS OPTIONS请求与HEAD类似,一般也是用于客户端查看服务器的性能。 这个方法会请求服务器返回该资源所支持的所有HTTP请求方法,该方法会用'*'来代替资源名称,向服务器发送OPTIONS请求,可以测试服务器功能是否正常。JavaScript的XMLHttpRequest对象进行CORS跨域资源共享时,就是使用OPTIONS方法发送嗅探请求,以判断是否有对指定资源的访问权限。
TRACE TRACE请求服务器回显其收到的请求信息,该方法主要用于HTTP请求的测试或诊断。
PATCH PATCH方法出现的较晚,它在2010年的RFC 5789标准中被定义。PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同:1.PATCH一般用于资源的部分更新,而PUT一般用于资源的整体更新。2.当资源不存在时,PATCH会创建一个新的资源,而PUT只会对已在资源进行更新。

名词解释: 幂等:对同一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的。

注:

  • GET 可提交的数据量受到URL长度的限制,HTTP 协议规范没有对 URL 长度进行限制。这个限制是特定的浏览器及服务器对它的限制。

  • 理论上讲,POST 是没有大小限制的,HTTP 协议规范也没有进行大小限制,出于安全考虑,服务器软件在实现时会做一定限制。

8.交换机和路由器的区别?

定义

集线器、交换机都是做端口扩展的,就是扩大局域网(通常都是以太网)的接入点,也就是能让局域网可以连进来更多的电脑。是一种基于MAC(网卡的硬件地址)识别,能完成封装转化数据包功能的网络设备。 具有流量控制能力,主要用于组建局域网。例如:搭建一个公司网络,一般会使用交换机。常见的交换机种类以及以太网交换机、光纤交换机等。

路由器是用来做网间连接,也就是用来连接不同的网络。

区别

(1)交换机是一根网线上网,但是大家上网是分别拨号,各自使用自己的宽带,大家上网没有影响。而路由器比交换机多了一个虚拟拨号功能,通过同一台路由器上网的电脑是共用一个宽带账号,大家上网要相互影响。

(2)交换机工作在中继层,交换机根据MAC地址寻址。路由器工作在网络层,根据IP地址寻址,路由器可以处理TCP/IP协议,而交换机不可以。MAC地址通常是硬件自带的,由网卡生产商来分配的,而且已经固化到了网卡中去,一般来说是不可更改的。而IP地址则通常由网络管理员或系统自动分配。

(3)交换机可以使连接它的多台电脑组成局域网,如果还有代理服务器的话还可以实现同时上网功能而且局域网所有电脑是共享它的带宽速率的,但是交换机没有路由器的自动识别数据包发送和到达地址的功能。路由器可以自动识别数据包发送和到达的地址,路由器相当于马路上的警察,负责交通疏导和指路的。

(4)路由器专管入网,交换机只管配送,路由路由就是给你找路让你上网的,交换机只负责开门,交换机上面要没有路由你是上不了网的。

(5)路由器提供了防火墙的服务。路由器仅仅转发特定地址的数据包,不传送不支持路由协议的数据包传送和未知目标网络数据包的传送,从而可以防止广播风暴。

三层交换机的主要功能仍是数据交换,它的路由功能通常比较简单,因为它所面对的主要是简单的局域网连接,路由路径没有路由器那么复杂,它用在局域网中的主要用途还是提供快速数据交换功能,满足局域网数据交换频繁的应用特点。

路由器的主要功能还是路由功能,它的路由功能更多的体现在不同类型网络之间的互联上,如局域网与广域网之间的连接、不同协议的网络之间的连接等,所以路由器主要是用于不同类型的网络之间。它最主要的功能就是路由转发,解决好各种复杂路由路径网络的连接就是它的最终目的,所以路由器的路由功能通常非常强大,不仅适用于同种协议的局域网间,更适用于不同协议的局域网与广域网间。它的优势在于选择最佳路由、负荷分担、链路备份及和其他网络进行路由信息的交换等等路由器所具有功能。为了与各种类型的网络连接,路由器的接口类型非常丰富,而三层交换机则一般仅同类型的局域网接口,非常简单。

9.什么是VLAN,有什么作用?

(1)概念

Virtual Local Area Network(虚拟局域网)能将网络划分为多个广播域,从而有效地控制广播风暴的发生,以及使网络的拓扑结构变得非常灵活的优点外,还可以用于控制网络中不同部门、不同站点之间的互相访问

1、要知道192.168.1.2/30和192.168.2.6/30都属于不同的网段,都必须要通过路由器才能进行访问,凡是不同网段间要互相访问,都必须通过路由器。 

2、VLAN本质就是指一个网段,之所以叫做虚拟的局域网,是因为它是在虚拟的路由器的接口下创建的网段。

当一个交换机上的所有端口中有至少一个端口属于不同网段的时候,当路由器的一个物理端口要连接2个或者以上的网段的时候,就是VLAN发挥作用的时候,这就是VLAN的目的。

(2)作用

广播风暴防范

限制网络上的广播,将网络划分为多个VLAN可减少参与广播风暴的设备数量。VLAN分段可以防止广播风暴波及整个网络。VLAN可以提供建立防火墙的机制,防止交换网络的过量广播。使用VLAN,可以将某个交换端口或用户赋予某一个特定的VLAN组,该VLAN组可以在一个交换网中或跨接多个交换机,在一个VLAN中的广播不会送到VLAN之外。同样,相邻的端口不会收到其他VLAN产生的广播。这样可以减少广播流量,释放带宽给用户应用,减少广播的产生。

安全

增强局域网的安全性含有敏感数据的用户组可与网络的其余部分隔离,从而降低泄露机密信息的可能性。不同VLAN内的报文在传输时是相互隔离的,即一个VLAN内的用户不能和其他VLAN内的用户直接通信,如果不同VLAN要进行通信,则需要通过路由器或三层交换机等三层设备。

成本降低

成本高昂的网络升级需求减少,现有带宽和上行链路的利用率更高,因而可节约成本。

性能提高

将第二层平面网络划分为多个逻辑工作组(广播域)可以减少网络上不必要的流量并提高性能。

提高人员工作效率

VLAN为网络管理带来了方便,因为有相似网络需求的用户将共享同一个VLAN。

简化项目管理或应用管理

VLAN将用户和网络设备聚合到一起,以支持商业需求或地域上的需求。通过职能划分,项目管理或特殊应用的处理都变得十分方便,例如可以轻松管理教师的电子教学开发平台。此外,也很容易确定升级网络服务的影响范围。 

增加了网络连接的灵活性

借助VLAN技术,能将不同地点、不同网络、不同用户组合在一起,形成一个虚拟的网络环境,就像使用本地VLAN一样方便、灵活、有效。VLAN可以降低移动或变更工作站地理位置的管理费用,特别是一些业务情况有经常性变动的公司使用了VLAN后,这部分管理费用大大降低。 

10.什么是VXLAN,有什么作用?

https://www.cnblogs.com/bakari/p/11131268.html

(1)简介

VxLAN 全称是 Visual eXtensible Local Area Network(虚拟扩展本地局域网),从名字上就知道,这是一个 VLAN 的扩展协议。

VxLAN 本质上是一种隧道封装技术。它使用 TCP/IP 协议栈的惯用手法——封装/解封装技术,将 L2 的以太网帧(Ethernet frames)封装成 L4 的 UDP 数据报(datagrams),然后在 L3 的网络中传输,效果就像 L2 的以太网帧在一个广播域中传输一样,实际上是跨越了 L3 网络,但却感知不到 L3 网络的存在。

(2)作用

1、VLAN ID 数量限制

虚拟化技术的发展,使得以前以单个物理设备组网的方式,逐步向以虚拟设备的方式过渡。

以前一台物理设备(一台服务器也好,一台网络设备也好),能支持几十个端口就已经很了不起了,所以使用 VLAN 是绰绰有余,但是虚拟化环境下就大不同了,一台物理主机可能虚拟出上百上千台虚拟设备,整个云数据中心可能要划分超过成千上万个的广播域,而 VLAN 被限制为最多 4094 个,这就显得捉襟见肘了。

2、更好地利用多条网络链路

VLAN 使用 STP 来管理多条网络链路,避免数据传输时出现的环路。STP 根据优先级和成本,只会选择其中一条链路工作,其余链路作为备用链路,也就是主备模式(active-passive)。这样虽然既避免了环路,也增强了可用性,但没有充分利用多条线路来提升性能,对于用户来说,等于是花 N 倍的钱,却只享受到了 1 倍的服务。

VxLAN 则不然,VxLAN 可以在 L3 层网络上,透明地传输 L2 层数据,这让它可以利用 ECMP (Equal-cost multi-path,等价多路径) 等协议实现多条路径同时工作,也就是 active-active 模式。这样当网络流量较大时,可以实现流量的负载均衡,提升数据传输性能。

3、TOR 交换机 MAC 地址表限制

交换机的原理是根据 MAC 地址表完成数据包的二层转发。在虚拟化技术没出现之前,数据中心的 TOR(Top of Rack) 交换机的一个端口连接一台物理主机,并对应一个 MAC 地址,当虚拟化技术出现之后,一台物理主机虚拟出几十甚至上百台虚拟机,TOR 交换机的一个端口虽然还是连接一台物理主机,但却对应多个 MAC 地址(这还在不算 VLAN 划分的情况下),如下图所示:

这无疑会造成 TOR MAC 地址表的膨胀,交换机本身 MAC 表的空间是有限的,如果溢出,就会造成交换机的不断泛洪,增加了处理负担。

如果使用 VxLAN 则不然,VxLAN 使用 VTEP 封装虚拟机的二层帧,在三层网络上传输,通常,一台物理机对应一个 VTEP,一个 VTEP 可以被该台物理机上的所有虚拟机共有,所以,对于 TOR 交换机的 MAC 地址表来说,一台物理机只用记录一条 VTEP 信息即可。这样就避免了 MAC 地址表暴增的问题。

4、灵活的虚拟机部署和迁移

采用 VLAN 的虚拟网络环境,不存在 overlay 网络,只有 underlay 网络。也就是说 虚拟机的 VLAN 数据包直接在物理网络上传输,和物理网络上的 VLAN 数据包融合在一起,这样的好处是虚拟机能直接访问到物理网络的设备,但坏处也很明显,虚拟网络无法打破物理网络的界限,具体表现在虚拟机的部署和迁移不太灵活。

  • 部署 :如果要在 VLAN 100 上部署虚拟机,那么只能在支持 VLAN 100 的物理机上部署,如下图所示,假设左右两个区域分属 VLAN 100 和 VLAN 200,现在 VLAN 100 已经部署了很多虚拟机,而 VLAN 200 却才部署了少量的虚拟机,如果这时需要继续往 VLAN 100 部署新的虚拟机,那么也只能选择在左边区域部署,这就会造成左边区域负担过重。
  • 迁移 :同样,如果从左边区域往右边区域迁移虚拟机,因为两边分属于不同的 VLAN,虚机所分配的 IP 地址不同,无法直接进行迁移,这会造成整个集群机器的负载分配不均。

使用 VxLAN 则完全不全在这些问题,通过 VxLAN 的封装,在一个 L3 网络上构建了 L2 网络,或者说基于 underlay 网络的 overlay 网络,虚拟机的数据可以打破 L2 网络的限制,在 L3 网络上传输,虚拟机的部署和迁移也不受物理网络的限制,可以灵活部署和迁移,使得整个数据中心保持一个平均的利用率。

11.http协议(报文结构,断点续传,多线程下载,什么是长连接)

(1)报文结构

(2)断点续传的实现原理·

HTTP1.1协议(RFC2616)中定义了断点续传相关的HTTP头 Range和Content-Range字段
  1.客户端下载一个1024K的文件,已经下载了其中512K
  2. 网络中断,客户端请求续传,因此需要在HTTP头中申明本次需要续传的片段:
       Range:bytes=512000-
    这个头通知服务端从文件的512K位置开始传输文件
  3. 服务端收到断点续传请求,从文件的512K位置开始传输,并且在HTTP头中增加:
    Content-Range:bytes 512000-/1024000
    并且此时服务端返回的HTTP状态码应该是206,而不是200。

客户端通过并发的请求相同资源的不同片段,来实现对某个资源的并发分块下载。从而达到快速下载的目的。目前流行的FlashGet和迅雷基本都是这个原理。

(3)多线程下载的原理
下载工具开启多个发出HTTP请求的线程;
每个http请求只请求资源文件的一部分:Content-Range: bytes 20000-40000/47000;
合并每个线程下载的文件。

(4)长连接

如何理解HTTP协议是无状态的

  HTTP协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。

 在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。

但从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:

Connection:keep-alive

  在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。

HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。

12.tcp协议(建连过程,慢启动,滑动窗口,七层模型)

 (1)HTTP协议与TCP/IP协议的关系

  HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。

(2)慢启动

在网络实际的传输过程中,会出现拥塞的现象,网络上充斥着非常多的数据包,但是却不能按时被传送,形成网络拥塞,其实就是和平时的堵车一个性质了。TCP设计中也考虑到这一点,使用了一些算法来检测网络拥塞现象,如果拥塞产生,变会调整发送策略,减少数据包的发送来缓解网络的压力。

https://www.cnblogs.com/ggjucheng/archive/2012/02/02/2335994.html

(3)七层模型

https://blog.csdn.net/mccand1234/article/details/51590804

物理层

物理层(physical layer)的主要功能是完成相邻结点之间原始比特流传输。物理层协议关心的典型问题是使用什么样的物理信号来表示数据0和1。1位持续的时间多长。数据传输是否可同时在两个方向上进行。最初的廉洁如何建立以及完成通信后连接如何终止。物理接口(插头和插座)有多少针以及各针的作用。物理层的设计主要涉及物理层接口的机械、电气、功能和过电特性,以及物理层接口连接的传输介质等问题。物理层的实际还涉及到通信工程领域内的一些问题。

数据链路层

数据链路层(data link layer)的主要功能是如何在不可靠的物理线路上进行数据的可靠传输。数据链路层完成的是网络中相邻结点之间可靠的数据通信。为了保证书觉得可靠传输,发送出的数据针,并按顺序传送个针。由于物理线路不可靠,因此发送方发出的数据针有可能在线路上出错或丢失,从而导致接受方无法正确接收数据。为了保证能让接收方对接收到的数据进行正确的判断,发送方位每个数据块计算出CRC(循环冗余检验)并加入到针中,这样接收方就可以通过重新计算CRC来判断接收到的数据是否正确。一旦接收方发现接收到的数据有错误,则发送方必须重新传送这一数据。然而,相同的数据多次传送也可能是接收方收到重复的数据。
数据链路层要解决的另一个问题是防止高速发送方的数据把低速接收方“淹没”。因此需要某种信息流量控制机制使发送方得知接收方当前还有多少缓存空间。为了控制的方便,流量控制常常和差错处理一同实现。
在广域网中,数据链路层负责主机IMP、IMP-IMP之间数据的可靠传送。在局域网中,数据链路层负责制及之间数据的可靠传输。

网络层

网络层(network layer)的主要功能是完成网络中主机间的报文传输,其关键问题之一是使用数据链路层的服务将每个报文从源端传输到目的端。在广域网中,这包括产生从源端到目的端的路由,并要求这条路径经过尽可能少的IMP。如果在子网中同时出现过多的报文,子网就可能形成拥塞,因为必须加以避免这种情况的出现。
当报文不得不跨越两个或多个网络时,又会带来很多新问题。比如在单个局域网中,网络层是冗余的,因为报文是直接从一台计算机传送到另一台计算机的,因此网络层所要做的工作很少。

ping

ping在主机和服务器之间传递控制消息,属于ICMP协议,但是ICMP协议是TCP/IP的子协议。
ping 不通可能a.网络不通 b.对方设置了防火墙。

传输层

传输层(transport layer)的主要功能是实现网络中不同主机上的用户进程之间可靠的数据通信。
传输层要决定会话层用户(最终对网络用户)提供什么样的服务。最好的传输连接是一条无差错的、按顺序传送数据的管道,即传输层连接时真正的点到点。
在TCP/IP模型中,传输层的功能是使源端主机和目标端主机上的对等实体可以进行会话。在传输层定义了两种服务质量不同的协议。即:传输控制协议TCP(transmission control protocol)和用户数据报协议UDP(user datagram protocol)。  
  TCP协议是一个面向连接的、可靠的协议。它将一台主机发出的字节流无差错地发往互联网上的其他主机。在发送端,它负责把上层传送下来的字节流分成报文段并传递给下层。在接收端,它负责把收到的报文进行重组后递交给上层。TCP协议还要处理端到端的流量控制,以避免缓慢接收的接收方没有足够的缓冲区接收发送方发送的大量数据。  
  UDP协议是一个不可靠的、无连接协议,主要适用于不需要对报文进行排序和流量控制的场合。

会话层

会话层(SESSION LAYER)允许不同机器上的用户之间建立会话关系。会话层循序进行类似的传输层的普通数据的传送,在某某些场合还提供了一些有用的增强型服务。允许用户利用一次会话在远端的分时系统上登陆,或者在两台机器间传递文件。
会话层提供的服务之一是管理对话控制。会话层允许信息同时双向传输,或任一时刻只能单向传输。如果属于后者,类似于物理信道上的半双工模式,会话层将记录此时该轮到哪一方。一种与对话控制有关的服务是令牌管理(token management)。有些协议会保证双方不能同时进行同样的操作,这一点很重要。为了管理这些活动,会话层提供了令牌,令牌可以在会话双方之间移动,只有持有令牌的一方可以执行某种关键性操作。另一种会话层服务是同步。如果在平均每小时出现一次大故障的网络上,两台机器简要进行一次两小时的文件传输,试想会出现什么样的情况呢?每一次传输中途失败后,都不得不重新传送这个文件。当网络再次出现大故障时,可能又会半途而废。为解决这个问题,会话层提供了一种方法,即在数据中插入同步点。每次网络出现故障后,仅仅重传最后一个同步点以后的数据(这个其实就是断点下载的原理)。

表示层

表示层(presentation layer)用于完成某些特定功能,对这些功能人们常常希望找到普遍的解决办法,而不必由每个用户自己来实现。表示层以下各层只关心从源端机到目标机到目标机可靠的传送比特流,而表示层关心的是所传送的信息的语法和语义。表示层服务的一个典型例子就是大家一致选定的标准方法对数据进行编码。大多数用户程序之间并非交换随机比特,而是交换诸如人名、日期、货币数量和发票之类的信息。这些对象使用字符串、整型数、浮点数的形式,以及由几种简单类型组成的数据结构来表示的。
在网络上计算机可能采用不同的数据表示,所以需要在数据传输时进行数据格式转换。为了让采用不同数据表示法的计算机之间能够相互通信而且交换数据,就要在通信过程中使用抽象的数据结构来表示所传送的数据。而在机器内部仍然采用各自的标准编码。管理这些抽象数据结构,并在发送方将机器的内部编码转换为适合网上传输的传送语法以及在接收方做相反的转换等噢年工作都是由表示层来完成的。
另外,表示层还涉及数据压缩和解压、数据加密和解米等工作(winrar的那一套)。

应用层

连网的目的在于支持运行于不同计算机的进程彼此之间的通信,而这些进程则是为用户完成不同人物而设计的。可能的应用是多方面的,不受网络结构的限制。应用层(app;ocation layer)包括大量人们普遍需要的协议。虽然,对于需要通信的不同应用来说,应用层的协议都是必须的。例如:http、ftp。
由于每个应用有不同的要求,应用层的协议集在OSI模型中并没有定义。但是,有些确定的应用层协议,包括虚拟终端、文件传输、电子邮件等都可以作为标准化的候选

13.webservice协议(wsdl/soap格式,与rest协议的区别)

(1)wsdl:web service description language

说明服务在哪里,如何调用,其实就是一个使用说明书。

1、ws所提供的方法-即服务

2、WS的名称

3、WS的地址

(2)soap:简单对象访问协议

交换数据的一种协议规范,是一种轻量的、简单的、基于XML标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息。

SOAP协议的范本:-请求示例:

以下发出HTTP请求,但不同的是向服务器发送的是XML数据!

SOAP协议:-响应示例:

响应的信息,同发送信息一样,先必须是HTTP协议,然后再遵循SOAP协议。

https://blog.csdn.net/qq_18895659/article/details/51714968

(3)SOAP和REST的区别

a.SOAP是一种具体的通讯协议,REST是一种规范。

b.SOAP(Simple Object Access Protocol)简单对象访问协议,是基于HTTP的一种异构系统通信的协议,说白了就是xml文档传输,之所以会有它,就是在于不同语言C,C++,JAVA等语言开发的系统进行通信,是WebService就是基于SOAP协议的,确实是一种比较传统的SOA解决方案。

REST(Rerepresentational State Transfer)是外国一位博士提出的一种架构风格,从资源状态转换角度看待我们的资源(如此简洁,明了),所以外国人是挺牛的,但也是基于SOAP协议进行通信。

c.SOAP比较复杂,基于XML,有对应规范;REST利用HTTP请请求方式GET,POST,PUT约定事务操作。简单的说,SOAP通过传输XML,XML定义了请求和响应的具体数据,要进行的操作等等;而REST则是另一种约定,比如请求/user/1001这个RUL,GET方式返回id为1001的user信息,POST方式则是更新id为1001的user信息,DELETE删除等。

soap示例


rest示例

https://www.ibm.com/developerworks/cn/webservices/0907_rest_soap/index.html

14.spdy/http2.0协议是否有了解

(1)SPDY 可以说是综合了 HTTPS 和 HTTP 两者有点于一体的传输协议,主要解决:

  1. 降低延迟,针对 HTTP 高延迟的问题,SPDY 优雅的采取了多路复用(multiplexing)。多路复用通过多个请求 stream 共享一个 tcp 连接的方式,解决了 HOL blocking 的问题,降低了延迟同时提高了带宽的利用率。
  2. 请求优先级(request prioritization)。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY 允许给每个 request 设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的 html 内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。
  3. header 压缩。前面提到 HTTP1.x 的 header 很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。
  4. 基于 HTTPS 的加密协议传输,大大提高了传输数据的可靠性。
  5. 服务端推送(server push),采用了 SPDY 的网页,例如我的网页有一个 sytle.css 的请求,在客户端收到 sytle.css 数据的同时,服务端会将 sytle.js 的文件推送给客户端,当客户端再次尝试获取 sytle.js 时就可以直接从缓存中获取到,不用再发请求了。SPDY 构成图:

SPDY 位于 HTTP 之下,TCP 和 SSL 之上,这样可以轻松兼容老版本的 HTTP 协议 (将 HTTP1.x 的内容封装成一种新的 frame 格式),同时可以使用已有的 SSL 功能。

(2)HTTP2.0 可以说是 SPDY 的升级版(其实原本也是基于 SPDY 设计的),但是,HTTP2.0  跟 SPDY 仍有不同的地方,主要是以下两点:

  • HTTP2.0  支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
  • HTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATE

HTTP2.0 的新特性

  • 新的二进制格式(Binary Format),HTTP1.x 的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认 0 和 1 的组合。基于这种考虑 HTTP2.0 的协议解析决定采用二进制格式,实现方便且健壮。
  • 多路复用(MultiPlexing),即连接共享,即每一个 request 都是是用作连接共享机制的。一个 request 对应一个 id,这样一个连接上可以有多个 request,每个连接的 request 可以随机的混杂在一起,接收方可以根据 request 的 id 将 request 再归属到各自不同的服务端请求里面。
  • header 压缩,如上文中所言,对前面提到过 HTTP1.x 的 header 带有大量信息,而且每次都要重复发送,HTTP2.0 使用 encoder 来减少需要传输的 header 大小,通讯双方各自 cache 一份 header fields 表,既避免了重复 header 的传输,又减小了需要传输的大小。
  • 服务端推送(server push),同 SPDY 一样,HTTP2.0 也具有 server push 功能。目前,有大多数网站已经启用 HTTP2.0,例如 YouTuBe淘宝网等网站,利用 chrome 控制台可以查看是否启用 H2:

15.NIO的好处,Netty线程模型,什么是零拷贝

(1)面向Stream和面向Buffer

Java NIO和IO之间最大的区别是IO是面向流(Stream)的,NIO是面向块(buffer)的,所以,这意味着什么?

面向流意味着从流中一次可以读取一个或多个字节,拿到读取的这些做什么你说了算,这里没有任何缓存(这里指的是使用流没有任何缓存,接收或者发送的数据是缓存到操作系统中的,流就像一根水管从操作系统的缓存中读取数据)而且只能顺序从流中读取数据,如果需要跳过一些字节或者再读取已经读过的字节,你必须将从流中读取的数据先缓存起来。

面向块的处理方式有些不同,数据是先被 读/写到buffer中的,根据需要你可以控制读取什么位置的数据。这在处理的过程中给用户多了一些灵活性,然而,你需要额外做的工作是检查你需要的数据是否已经全部到了buffer中,你还需要保证当有更多的数据进入buffer中时,buffer中未处理的数据不会被覆盖

(2)阻塞IO和非阻塞IO

所有的Java IO流都是阻塞的,这意味着,当一条线程执行read()或者write()方法时,这条线程会一直阻塞知道读取到了一些数据或者要写出去的数据已经全部写出,在这期间这条线程不能做任何其他的事情

java NIO的非阻塞模式(Java NIO有阻塞模式和非阻塞模式,阻塞模式的NIO除了使用Buffer存储数据外和IO基本没有区别)允许一条线程从channel中读取数据,通过返回值来判断buffer中是否有数据,如果没有数据,NIO不会阻塞,因为不阻塞这条线程就可以去做其他的事情,过一段时间再回来判断一下有没有数据

NIO的写也是一样的,一条线程将buffer中的数据写入channel,它不会等待数据全部写完才会返回,而是调用完write()方法就会继续向下执行

(3)Selectors

Java NIO的selectors允许一条线程去监控多个channels的输入,你可以向一个selector上注册多个channel,然后调用selector的select()方法判断是否有新的连接进来或者已经在selector上注册时channel是否有数据进入。selector的机制让一个线程管理多个channel变得简单。

旧的IO处理方式

InputStream input = ... ; // get the InputStream from the client socket
 
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
 
String nameLine   = reader.readLine();
String ageLine    = reader.readLine();
String emailLine  = reader.readLine();
String phoneLine  = reader.readLine();

NIO处理方式

ByteBuffer buffer = ByteBuffer.allocate(48);
 
int bytesRead = inChannel.read(buffer);

注意第二行从channel中读取数据到ByteBuffer,当这个方法返回你不知道是否你需要的所有数据都被读到buffer了,你所知道的一切就是有一些数据被读到了buffer中,但是你并不知道具体有多少数据,这使程序的处理变得稍微有些困难

想象一下,调用了read(buffer)方法后,只有半行数据被读进了buffer,例如:“Name: An”,你能现在就处理数据吗?当然不能。你需要等待直到至少一整行数据被读到buffer中,在这之前确保程序不要处理buffer中的数据

你如何知道buffer中是否有足够的数据可以被处理呢?你不知道,唯一的方法就是检查buffer中的数据。可能你会进行几次无效的检查(检查了几次数据都不够进行处理),这会令程序设计变得比较混乱复杂

ByteBuffer buffer = ByteBuffer.allocate(48);
 
int bytesRead = inChannel.read(buffer);
 
while(! bufferFull(bytesRead) ) {
    bytesRead = inChannel.read(buffer);
}

Java nio读取文件内容源码

         File file = new File(bigExcelFile);
         
        //Get file channel in readonly mode
        FileChannel fileChannel = new RandomAccessFile(file, "r").getChannel();
         
        //Get direct byte buffer access using channel.map() operation
        MappedByteBuffer buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
         
        // the buffer now reads the file as if it were loaded in memory.
        System.out.println(buffer.isLoaded());  //prints false
        System.out.println(buffer.capacity());  //Get the size based on content size of file
         
        //You can read the file from this buffer the way you like.
        for (int i = 0; i < buffer.limit(); i++)
        {
            System.out.print((char) buffer.get()); //Print the content of file
        }

(4)介绍Netty线程模型前,首先会介绍下经典的Reactor线程模型,目前大多数网络框架都是基于Reactor模式进行设计和开发,Reactor模式基于事件驱动,非常适合处理海量的I/O事件,Reactor模式首先是事件驱动的,有一个或多个并发输入源,有一个Service Handler,有多个Request Handlers;这个Service Handler会同步的将输入的请求(Event)多路复用的分发给相应的Request Handler。

Reactor单线程模型

单线程模型下,所有的IO操作都由同一个Reactor线程来完成,负责接收客户端的连接,读取消息,发送应答

Reactor多线程模型

由一个Reactor线程-Acceptor线程用于监听服务端,接收客户端连接请求,网络I/O操作读、写等由Reactor线程池负责处理,绝大多数场景下,Reactor多线程模型都可以满足性能需求,但是,在极个别特殊场景中,一个Reactor线程负责监听和处理所有的客户端连接可能会存在性能问题。例如并发百万客户端连接,或者服务端需要对客户端握手进行安全认证,但是认证本身非常损耗性能

Reactor主从多线程模型

服务端使用一个独立的主Reactor线程池来处理客户端连接,当服务端收到连接请求时,从主线程池中随机选择一个Reactor线程作为Acceptor线程处理连接 链路建立成功后,将新创建的SocketChannel注册到sub reactor线程池的某个Reactor线程上,由它处理后续的I/O操作

Netty线程模型

Netty同时支持Reactor单线程模型 、Reactor多线程模型和Reactor主从多线程模型,用户可根据启动参数配置在这三种模型之间切换,服务端启动时,通常会创建两个NioEventLoopGroup实例,对应了两个独立的Reactor线程池

EventLoopGroup bossGroup = new NioEventLoopGroup(1);  
EventLoopGroup workerGroup = new NioEventLoopGroup();  
try {  
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossGroup, workerGroup)
     .channel(NioServerSocketChannel.class)
     .option(ChannelOption.SO_BACKLOG, 100)
     .handler(new LoggingHandler(LogLevel.INFO))
     .childHandler(new ChannelInitializer() {
         @Override
         public void initChannel(SocketChannel ch) throws Exception {
               ......

bossGroup负责处理客户端的连接请求,workerGroup负责处理I/O相关的操作,执行系统Task、定时任务Task等。

用户可根据服务端引导类ServerBootstrap配置参数选择Reactor线程模型,进而最大限度地满足用户的定制化需求;同时,为了最大限度地提升性能,netty很多地方采用了无锁化设计,如为每个Channel绑定唯一的EventLoop,这意味着同一个Channel生命周期内的所有事件都将由同一个Reactor线程来完成,这种串行化处理方式有效地避免了多线程操作之间锁的竞争和上下文切换带来的开销。此外,每个Reactor线程配备了一个task队列和Delay task队列,分别用于存放系统Task和周期性Task,也就是说每个Reactor线程不仅要处理I/O事件,还会处理一些系统任务和调度任务。

(5)零拷贝

拷贝的背景:

当应用程序需要读取文件的时候,内核首先通过DMA技术将文件内容从磁盘读入内核中的buffer,然后Java应用进程再从内核的buffer将数据读取到应用程序的buffer。

零拷贝是指计算机操作的过程中,CPU不需要为数据在内存之间的拷贝消耗资源。而它通常是指计算机在网络上发送文件时,不需要将文件内容拷贝到用户空间(User Space)而直接在内核空间(Kernel Space)中传输到网络的方式。Zero Copy的模式中,避免了数据在用户空间和内存空间之间的拷贝,从而提高了系统的整体性能。Linux中的sendfile()以及Java NIO中的FileChannel.transferTo()方法都实现了零拷贝的功能,而在Netty中也通过在FileRegion中包装了NIO FileChannel.transferTo()方法实现了零拷贝。

a.传统方法->把字节从文件拷贝到套接字

File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);

拷贝的操作需要四次用户模式和内核模式间的上下文切换,而且在操作完成前数据被复制了四次

  1. read() 调用引发了一次从用户模式到内核模式的上下文切换。在内部,发出 sys_read()(或等效内容)以从文件中读取数据。直接内存存取(direct memory access,DMA)引擎执行了第一次拷贝,它从磁盘中读取文件内容,然后将它们存储到一个内核地址空间缓存区中。
  2. 所需的数据被从读取缓冲区拷贝到用户缓冲区,read() 调用返回。该调用的返回引发了内核模式到用户模式的上下文切换(又一次上下文切换)。现在数据被储存在用户地址空间缓冲区。
  3. send() 套接字调用引发了从用户模式到内核模式的上下文切换。数据被第三次拷贝,并被再次放置在内核地址空间缓冲区。但是这一次放置的缓冲区不同,该缓冲区与目标套接字相关联。
  4. send() 系统调用返回,结果导致了第四次的上下文切换。DMA 引擎将数据从内核缓冲区传到协议引擎,第四次拷贝独立地、异步地发生 。

 b.transferTo

transferTo() 方法将数据从文件通道传输到了给定的可写字节通道。在内部,它依赖底层操作系统对零拷贝的支持;在 UNIX 和各种 Linux 系统中,此调用被传递到 sendfile() 系统调用中

transferTo() 方法引发 DMA 引擎将文件内容拷贝到一个读取缓冲区。然后由内核将数据拷贝到与输出套接字相关联的内核缓冲区。数据的第三次复制发生在 DMA 引擎将数据从内核套接字缓冲区传到协议引擎时。改进的地方:我们将上下文切换的次数从四次减少到了两次,将数据复制的次数从四次减少到了三次(其中只有一次涉及到了 CPU)。但是这个代码尚未达到我们的零拷贝要求。如果底层网络接口卡支持收集操作 的话,那么我们就可以进一步减少内核的数据复制。在 Linux 内核 2.4 及后期版本中,套接字缓冲区描述符就做了相应调整,以满足该需求。这种方法不仅可以减少多个上下文切换,还可以消除需要涉及 CPU 的重复的数据拷贝。对于用户方面,用法还是一样的,但是内部操作已经发生了改变:transferTo() 方法引发 DMA 引擎将文件内容拷贝到内核缓冲区

数据未被拷贝到套接字缓冲区。取而代之的是,只有包含关于数据的位置和长度的信息的描述符被追加到了套接字缓冲区。DMA 引擎直接把数据从内核缓冲区传输到协议引擎,从而消除了剩下的最后一次 CPU 拷贝

(6)Netty的零拷贝

  • Netty 提供了 CompositeByteBuf 类, 它可以将多个 ByteBuf 合并为一个逻辑上的 ByteBuf, 避免了各个 ByteBuf 之间的拷贝.
  • 通过 wrap 操作, 我们可以将 byte[] 数组、ByteBuf、ByteBuffer等包装成一个 Netty ByteBuf 对象, 进而避免了拷贝操作.
  • ByteBuf 支持 slice 操作, 因此可以将 ByteBuf 分解为多个共享同一个存储区域的 ByteBuf, 避免了内存的拷贝.
  • 通过 FileRegion 包装的FileChannel.tranferTo 实现文件传输, 可以直接将文件缓冲区的数据发送到目标 Channel, 避免了传统通过循环 write 方式导致的内存拷贝问题.

https://cloud.tencent.com/developer/article/1541200

16. 网络中的socket是指什么?

传输层实现端到端的通信。传输层连接的端点叫做套接字(socket)。根据RFC793的定义:端口号拼接到IP地址就构成了套接字。所谓套接字,实际上是一个通信端点,每个套接字都有一个套接字序号,包括主机的IP地址与一个16位的主机端口号,即形如(主机IP地址:端口号)。例如,如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)

总之,套接字Socket=(IP地址:端口号),套接字的表示方法是点分十进制的IP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定。

以上内容源于百度百科

猜你喜欢

转载自blog.csdn.net/u013984781/article/details/102454760