计算机网络
路由器和交换机的区别
- 工作层次不同:交换机工作在数据链路层,而路由器工作在网络层,交换机比路由器更简单,路由器比交换机能获取更多信息
- 数据转发所依据的对象不同。交换机的数据转发依据是利用物理地址或者说MAC地址来确定转发数据的目的地址,而路由器是依据ip地址进行工作的
- 传统的交换机只能分割冲突域,不能分割广播域;而路由器可以分割广播域
域名、IP、MAC
- 域名是我们取代记忆复杂的 IP 的一种解决方案
- IP 地址才是目标在网络中所被分配的节点。
- MAC 地址是对应目标网卡所在的固定地址。
URL组成
从上面的URL可以看出,一个完整的URL包括以下几部分:
- 协议部分:该URL的协议部分为"http:",这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在"HTTP"后面的"//"为分隔符
- 域名部分:该URL的域名部分为"www.aspxfans.com"。一个URL中,也可以使用IP地址作为域名使用
- 端口部分:跟在域名后面的是端口,域名和端口之间使用":"作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口80
- 虚拟目录部分:从域名后的第一个"/"开始到最后一个"/"为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是"/news/"
- 文件名部分:从域名后的最后一个"/"开始到"?"为止,是文件名部分,如果没有"?",则是从域名后的最后一个"/"开始到"#"为止,是文件部分,如果没有"?"和"#",那么从域名后的最后一个"/"开始到结束,都是文件名部分。本例中的文件名是"index.asp"。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名
- 锚部分:从"#"开始到最后,都是锚部分。本例中的锚部分是"name"。锚部分也不是一个URL必须的部分
- 参数部分:从"?"开始到"#"为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为"boardID=5&ID=24618&page=1"。参数可以允许有多个参数,参数与参数之间用"&"作为分隔符。
从输入URL到页面展示的详细过程
- 浏览器解析输入:地址栏会根据用户输入,做出如下判断:输入的是非 URL 结构的字符串,则会用浏览器默认的搜索引擎搜索该字符串;输入的是 URL 结构字符串,则会构建完整的 URL 结构,浏览器进程会将完整的 URL 通过进程间通信,即 IPC,发送给网络进程。
- DNS域名解析:在网络进程接收到 URL 后,并不是马上对指定 URL 进行请求。首先进行DNS 解析域名得到对应的 IP,然后通过 ARP 解析 IP 得到对应的 MAC地址。
- 浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。
- 浏览器向服务器发送HTTP请求,请求数据包
- 服务器处理请求
- 服务器响应请求
- 读取页面内容,浏览器渲染,解析html源码
- 生成Dom树、解析css样式、js交互
- 客户端和服务器交互
- Ajax异步查询
DNS的寻址过程
- DNS 解析域名的过程分为以下几个步骤:
- 浏览器缓存:询问浏览器 DNS 缓存
- 本地系统缓存:询问本地操作系统 DNS 缓存(即查找本地 host 文件)
- 路由器缓存,以上三步均为客服端的DNS缓存;
- ISP DNS 缓存:询问 ISP(Internet Service Provider)互联网服务提供商(例如电信、移动)的 DNS 服务器
- 询问根服务器,这个过程可以进行递归和迭代两种查找的方式,两者都是先询问顶级域名服务器查找,全球仅有13台根域名服务器,1个主根域名服务器,其余12为辅根域名服务器。根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器IP告诉本地DNS服务器;
- 顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的IP地址告诉本地DNS服务器;
- 主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,并重复该步骤直至找到正确纪录;
- 本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器建立链接。
- DNS占用53号端口,同时使用TCP和UDP协议。DNS在区域传输的时候使用TCP协议,其他时候使用UDP协议。
DNS污染、DNS劫持、泛洪攻击
- DNS劫持:DNS系统被入侵或人为的修改某些记录,如A记录,用专业的术语来讲就是通过某些手段取得某域名的解析记录控制权,进而修改此域名的解析结果,导致对该域名的访问由原IP地址转入到修改后的指定IP,其结果就是对特定的网址不能访问或访问的是假网址。
- 现行标准中 DNS 查询通常使用 UDP 协议并且没有任何验证机制,并且根据惯例查询者会接受第一个返回的结果而抛弃之后的。因此只需监控 53 端口(DNS 标准端口)的 UDP查询数据报并分析,一旦发现敏感查询,则抢先向查询者返回一个伪造的错误结果,从而实现 DNS 污染。DNS污染并无法阻止正确的DNS解析结果返回,但由于旁路产生的数据包发回的速度较国外DNS服务器发回的快,操作系统认为第一个收到的数据包就是返回结果,从而忽略其后收到的数据包。
- 泛洪攻击:
- SYN泛洪攻击(全连接):利用TCP的三次握手机制,攻击端利用伪造的IP地址向被攻击端发出请求,而被攻击端发出的响应报文将永远发送不到目的地,那么被攻击端在等待关闭这个连接的过程中消耗了资源,如果有成千上万的这种连接,主机资源将被耗尽,从而达到攻击的目的。我们可以利用路由器的TCP拦截功能,使网络上的主机受到保护。
- DHCP报文泛洪攻击:恶意用户利用工具伪造大量DHCP报文发送到服务器,一方面恶意耗尽了IP资源,使得合法用户无法获得IP资源;另一方面,如果交换机上开启了DHCP Snooping功能,会将接收到的DHCP报文上送到CPU。因此大量的DHCP报文攻击设备会使DHCP服务器高负荷运行,甚至会导致设备瘫痪。
- ARP报文泛洪攻击:类似DHCP泛洪,同样是恶意用户发出大量的ARP报文,造成L3设备的ARP表项溢出,影响正常用户的转发
网络模型
ARP
ARP 英文全名为:Address resolution protocol ,地址解析协议,ARP为IP与MAC提供动态映射,过程自动完成。当PC发出通信请求时,根据协议规定,它的目的地址必然是48bit的MAC地址的。MAC并不能和IP直接去通信。那么就需我们的ARP协议来做相应的转换工作。
TCP
- tcp为什么要建立连接?
保证可靠传输。
- TCP为什么可靠一些?
三次握手,超时重传,流量控制,拥塞控制。
- 哪种应用场景会使用TCP协议,使用它的意义?
当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议,建立一个 TCP 连接是需要客户端与服务器端达成三个信息的共识。
- Socket:由 IP 地址和端口号组成
- 序列号:用来解决乱序问题等
- 窗口大小:用来做流量控制
- TCP的数据被封装在一个IP数据报中:
- TCP首部如下图所示:
大小端字节序
字节序,就是指的超过一个字节的数据类型在内存中存储的顺序。大端字节序:高位字节数据存放在低地址处,低位数据存放在高地址处;小端字节序:高位字节数据存放在高地址处,低位数据存放在低地址处;TCP/IP协议传输数据时,字节序默认大端。
高低地址:在内存中,栈是向下生长的,以char arr[4]为例,(因为char类型数据只有一个字节,不存在字节序的问题)依次输出每个元素的地址,可以发现,arr[0]的地址最低,arr[3]的地址最高。
高低位:给一个十进制整数,123456,很明显左边的是高位,右边的是低位。计算机也是这样认为的。给一个16进制数,0x12345678,以字节为单位,从高位到低位依次是 0x12、0x34、0x56、0x78。
超时重传
https://blog.csdn.net/u010710458/article/details/79968648
TCP提供可靠的运输层。它使用的方法之一就是确认从另一端收到的数据。但数据和确认都有可能会丢失。TCP通过在发送时设置一个定时器来解决这种问题。如果当定时器溢出时还没有收到确认,它就重传该数据。对任何实现而言,关键之处就在于超时和重传的策略,即怎样决定超时间隔和如何确定重传的频率。对每个连接, TCP管理4个不同的定时器:
- 重传定时器使用于当希望收到另一端的确认。
- 坚持(persist)定时器使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口。
- 保活(keepalive)定时器可检测到一个空闲连接的另一端何时崩溃或重启。
- 2MSL定时器测量一个连接处于TIME_WAIT状态的时间。
慢启动和拥塞控制
拥塞避免算法和慢启动算法需要对每个连接维持两个变量:一个拥塞窗口cwnd和一个慢启动门限ssthresh。
- 慢启动算法:在主机刚开始发送数据报的时候先探测一下网络的状况,如果网络状况良好,发送方每发送一次报文段都能正确的接受确认报文段。那么就从小到大的增加拥塞窗口的大小,即增加发送窗口的大小。慢启动算法是慢启动的指数增加,初始设置cwnd为1个报文段,此后每收到一个确认就加倍,这会使窗口按指数方式增长:发送1个报文段,然后是2个,接着是4个等等。慢启动算法每经过一个传输轮次(认为发送方都成功接收接收方的确认),拥塞窗口cwnd就加倍。
- 拥塞避免算法:为了防止cwnd增加过快而导致网络拥塞,所以需要启动拥塞避免算法。拥塞避免算法使得cwnd缓慢的增加而不是加倍的增长,每经历过一次往返时间就使cwnd增加1,而不是加倍。这样使cwnd缓慢增长,比慢启动要慢的多。
- 当拥塞发生时候,两种算法如何配合工作?
无论是慢启动算法还是拥塞避免算法,只要判断网络出现拥塞,就要把慢启动开始门限(ssthresh)设置为发送窗口的一半(>=2),cwnd(拥塞窗口)设置为1,然后再使用慢启动算法,这样做的目的能迅速的减少主机向网络中传输数据,使发生拥塞的路由器能够把队列中堆积的分组处理完毕。
- 二者配合工作简单实例:
- TCP连接进行初始化的时候,cwnd=1,ssthresh=16。
- 连接刚开始使用慢启动算法发送数据,在慢启动算法开始时,cwnd的初始值是1,每次发送方收到一个ACK拥塞窗口就增加1,当ssthresh = cwnd时,就启动拥塞控制算法,拥塞窗口按照规律增长。
- 当cwnd=24时,网络出现超时,发送方收不到确认ACK,此时设置ssthresh=12(二分之一cwnd),并设置cwnd=1,然后重新开始慢启动算法,当cwnd = ssthresh = 12,慢启动算法变为拥塞控制算法,cwnd按照线性的速度进行增长。
四种拥塞控制算法
TCP 通过维护一个拥塞窗口来进行拥塞控制,拥塞控制的原则是:只要网络中没有出现拥塞,拥塞窗口的值就可以再增大一些,以便把更多的数据包发送出去,但只要网络出现拥塞,拥塞窗口的值就应该减小一些,以减少注入到网络中的数据包数。
TCP 拥塞控制算法发展的过程中出现了如下几种不同的思路:
- 基于丢包的拥塞控制:将丢包视为出现拥塞,采取缓慢探测的方式,逐渐增大拥塞窗口,当出现丢包时,将拥塞窗口减小,如 Reno、Cubic 等。
- 基于时延的拥塞控制:将时延增加视为出现拥塞,延时增加时增大拥塞窗口,延时减小时减小拥塞窗口,如 Vegas、FastTCP 等。
- 基于链路容量的拥塞控制:实时测量网络带宽和时延,认为网络上报文总量大于带宽时延乘积时出现了拥塞,如 BBR。
- 基于学习的拥塞控制:没有特定的拥塞信号,而是借助评价函数,基于训练数据,使用机器学习的方法形成一个控制策略,如 Remy。
快速重传及恢复
- 快速重传
快重传算法要求首先接收方收到一个失序的报文段后就立刻发出重复确认,而不要等待自己发送数据时才进行捎带确认。
例如当接收方成功的接受了发送方发送来的M1、M2并且分别给发送了ACK,现在接收方没有收到M3,而接收到了M4,显然接收方不能确认M4,因为M4是失序的报文段。如果根据可靠性传输原理接收方什么都不做,但是按照快速重传算法,在收到M4、M5等报文段的时候,不断重复的向发送方发送M2的ACK。该重复的ACK的目的在于让对方知道收到一个失序的报文段,并告诉对方自己希望收到的序号M3。如果接收方一连收到三个重复的ACK,那么发送方不必等待重传计时器到期,由发送方尽早重传未被确认的报文段。
- 快速恢复算法
当发送发连续接收到三个确认时,就执行乘法减小算法,把慢启动开始门限(ssthresh)减半,但是接下来并不执行慢启动算法,而是把cwnd设置为ssthresh的一半, 然后执行拥塞避免算法,使拥塞窗口缓慢增大,这就是快速恢复算法。
滑动窗口
滑动窗口(Sliding window)是一种流量控制技术。早期的网络通信中,通信双方不会考虑网络的拥挤情况直接发送数据。由于大家不知道网络拥塞状况,同时发送数据,导致中间节点阻塞掉包,谁也发不了数据,所以就有了滑动窗口机制来解决此问题。
滑动窗口协议是用来改善吞吐量的一种技术,即容许发送方在接收任何应答之前传送附加的包。接收方告诉发送方在某一时刻能送多少包(称窗口尺寸)。
TCP中采用滑动窗口来进行传输控制,滑动窗口的大小意味着接收方还有多大的缓冲区可以用于接收数据。发送方可以通过滑动窗口的大小来确定应该发送多少字节的数据。当滑动窗口为0时,发送方一般不能再发送数据报,但有两种情况除外,一种情况是可以发送紧急数据,例如,允许用户终止在远端机上的运行进程。另一种情况是发送方可以发送一个1字节的数据报来通知接收方重新声明它希望接收的下一字节及发送方的滑动窗口大小。
TCP和UDP的区别
- TCP提供可靠的传输(有序,无差错,不丢失,不重复); UDP提供不可靠的传输。
- TCP提供面向连接的传输,通信前要先建立连接(三次握手机制); UDP提供无连接的传输,通信前不需要建立连接。
3) TCP面向字节流的传输,因此它能将信息分割成组,并在接收端将其重组; UDP是面向数据报的传输,没有分组开销。
4) TCP提供拥塞控制和流量控制机制; UDP不提供拥塞控制和流量控制机制。
UDP实现TCP
如果要用UDP实现类似TCP的可靠传输,一般需要实现以下特性:
- 增加ack机制,确保发送到对端
- 增加seq机制,实现传输顺序化
- 增加MTU机制,确保传输有序缓冲
- 增加数据校验机制,确保传输的正确性
- 增加超时重传机制
TCP粘包和拆包
TCP属于传输层的协议,传输层除了有TCP协议外还有UDP协议。UDP不会发生粘包或拆包的现象,因为UDP是基于报文发送的,从UDP的帧结构可以看出,在UDP首部采用了16bit来指示UDP数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。
TCP是基于字节流的,虽然应用层和TCP传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界;另外从TCP的帧结构也可以看出,在TCP的首部没有表示数据长度的字段,基于上面两点,在使用TCP传输数据时,有粘包或者拆包现象发生的可能。
- 解决TCP粘包和拆包的方法:
- 发送端给每个数据包添加包首部,首部中应该包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。
- 发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
- 可以在数据包之间设置边界,如添加特殊符号,这样接收端通过这个边界就可以将不同的数据包拆分开。
tcp连接之半连接攻击和全连接攻击
- 半连接攻击
半连接攻击是一种攻击协议栈的攻击方式,就是攻击主机的一种攻击方式。通过将主机的资源消耗殆尽,从而导致应用层的程序无资源可用,导致无法运行。
在正常情况下,客户端连接服务端需要通过三次握手,首先客户端构造一个SYN连接数据包发送至服务端,自身进入SYN_SEND状态,当服务端收到客户端的SYN包之后,为其分配内存核心内存,并将其放置在半连接队列中,并会向客户端发送一个SYN包和ACK包,此刻服务端进入SYN_RECV态。客户端收到包之后,再次向服务端发送ACK确认包。至此连接建立完成,双方都进入ESTABLSHED状态。
半连接就是通过不断地构造客户端的SYN连接数据包发向服务端,等到服务端的半连接队列满的时候,后续的正常用户的连接请求将会被丢弃,从而无法连接到服务端。根据服务端的半连接队列的大小,不同主机的抵抗这种SYN攻击的能力也不一样。
- 如何来解决半连接攻击?
- 通过拓展半连接队列的大小来进行补救,但缺点是不能无限制的增加,这样会耗费过多的服务端资源,导致服务端性能低下。
- 现在主要通过syncookies或者syn中继机制来防范半连接攻击,不为半连接分配核心内存的方式来防范。syncookies 的原理就是当服务端收到客户端 SYN 包后,不会放到半连接队列里,而是通过 {src_ip,src_port,timestamp} 等计算一个 cookie(也就是一个哈希值),通过 SYN+ACK包返回给客户端,客户端返回一个 ACK 包,携带上这个 cookie,服务端通过校验可以直接把这个连接放入全连接队列。整个过程不需要半连接队列的参与。
- 全连接攻击
全连接攻击是通过消耗服务端进程数和连接数,只连接而不进行发送数据的一种攻击方式。当客户端连接到服务端,仅仅只是连接,此时服务端会为每一个连接创建一个进程来处理客户端发送的数据。但是客户端只是连接而不发送数据,此时服务端会一直阻塞在recv或者read的状态,如此一来,多个连接,服务端的每个连接都是处于阻塞状态从而导致服务端的崩溃。
- 如何来解决全连接攻击?
可以通过不为全连接分配进程处理的方式来防范全连接攻击,只有收到数据之后,再为其分配一个处理线程。具体的处理方式在accept返回之前是不分配处理线程的,直到接收相关的数据之后才为之提供一个处理过程。
例如在apache服务中,是通过预创建一定量的子进程作为处理连接继承。所有的自己进程都继承父进程的sockfd,每当有一个连接过来时,只有当accept返回时,才会为该链接分配一个进程来处理连接请求。子进程一直处于等待状态。如果出现值是连接存在,而始终不放数据,该链接的状态是SYN_RECV,在协议栈中,提供一个保活期给该链接,如果超过保活期还没有数据到来,服务端协议栈将会断开该链接。如果没有该保活期,虽然避免了ESTABLESHED状态的数量,但是SYN_RECV的数据量的增长仍旧是不可估算的,所以需要利用保活期来监控该链接是需要清除断开。
XSS攻击
XSS 即(Cross Site Scripting)中文名称为:跨站脚本攻击。XSS的重点不在于跨站点,而在于脚本的执行。那么XSS的原理是:恶意攻击者在web页面中会插入一些恶意的script代码。当用户浏览该页面的时候,那么嵌入到web页面中script代码会执行,因此会达到恶意攻击用户的目的。那么XSS攻击最主要有如下分类:反射型、存储型、及 DOM-based型。反射性和DOM-baseed型可以归类为非持久性XSS攻击。存储型可以归类为持久性XSS攻击。
协议、协议簇和协议栈
- 协议,通常指某一个协议,一般由某一个或者一组文件如rfc/draft来指定。
- 协议族,是指彼此相互关联的一组协议。
- 协议栈,是指某一组协议的关系以及该组协议的层次结构,一般有清晰的up/down依赖关系和上下行消息交互。
标志位及序号
ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。
- 序列号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表示此报文段的发送方的数据已经发送完毕,并要求释放运输连接
- URG:紧急指针是否有效,1表示某一位需要被优先处理
- PSH:提示接收端应用程序立即从TCP缓冲区把数据读走
- RST:对方要求重新建立链接,复位
三次握手与四次挥手
- 三次握手过程
- 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入Established(TCP连接成功)状态,完成三次握手。
- 四次挥手
- 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
- 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
- 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
- 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
- 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
- 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
为什么不能用两次握手进行连接?
防止出现失效的连接请求报文段被服务端接收的情况,从而产生错误。
"已失效的连接请求报文段"在这样一种情况下产生:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段,但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用"三次握手",那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用"三次握手"的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。
3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到Server端所有的报文都发送完了,才能发送FIN报文,因此不能一起发送,故需要四步握手。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
假设网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,该ACK可能丢失,Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK,Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。
所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
如何解决TIME_WAIT过多?
- 改为长连接,但长连接太多会导致服务器性能问题,而且PHP等脚本语言,需要通过proxy之类的软件才能实现长连接;
- 修改ipv4.ip_local_port_range,增大可用端口范围,但只能缓解问题,不能根本解决问题;
- 客户端程序中设置socket的SO_LINGER选项;
- 让TIME_WAIT状态可以重用,这样即使TIME_WAIT占满了所有端口,也不会拒绝新的请求造成障碍,打开tcp_tw_reuse和tcp_timestamps选项;
- 让TIME_WAIT尽快回收,打开tcp_tw_recycle和tcp_timestamps选项;
- 客户端机器设置tcp_max_tw_buckets为一个很小的值
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP设有一个保活计时器,显然客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
HTTP1.0、1.1、2.0、3.0的区别
- HTTP 1.0
- 短连接:每次发送请求都要重新建立tcp请求,即三次握手,非常浪费性能
- 无host头域,也就是http请求头里的host,
- 不允许断点续传,而且不能只传输对象的一部分,要求传输整个对象
- HTTP 1.1
- 长连接,流水线,使用connection:keep-alive,使用长连接
- host头域
- 由于长连接会给服务器造成压力
- HTTP 2.0
- 头部压缩,双方各自维护一个header的索引表,使得不需要直接发送值,通过发送key缩减头部大小
- 多路复用,使用多个stream,每个stream又分帧传输,使得一个tcp连接能够处理多个http请求
- 可以使用服务端推送
- HTTP 3.0
- 基于google的QUIC协议,而QUIC协议是使用udp实现的
- 减少了tcp三次握手时间,以及tls握手时间
- 解决了http 2.0中前一个stream丢包导致后一个stream被阻塞的问题
- 优化了重传策略,重传包和原包的编号不同,降低后续重传计算的消耗
- 连接迁移,不再用tcp四元组确定一个连接,而是用一个64位随机数来确定这个连接
- 更合适的流量控制
HTTP常见状态码
- 1xx(2种):通知
- 100 Continue:客户端应重新发送初始请求,并在请求中附上第一次请求时未提供的(可能很大或者包含敏感信息的)表示。客户端这次发送的请求不会被拒绝。
- 101 Switching Protocols:当客户端通过在请求里使用Upgrade报头,以通知服务器它想改用除HTTP协议之外的其他协议时,客户端将获得此响应代码。
- 2xx(3种):成功
- 200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
- 204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
- 206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
- 3xx(5种):重定向
- 301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
- 302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
- 303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;302与303的区别:后者明确表示客户端应当采用GET方式获取资源
- 304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
- 307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
- 4xx(4种):客户端错误
- 400 Bad Request:表示请求报文中存在语法错误;
- 401 Unauthorized:未经许可,需要通过HTTP认证;
- 403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
- 404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
- 5xx(2种):服务端错误
- 500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误;
- 503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
HTTP请求/响应报文结构
- HTTP请求报文由四个部分组成:请求行、请求头、空行、请求数据。
- HTTP响应报文由三个部分组成:响应行、响应头、响应体。
http和https的区别
- https协议要申请CA证书;
- http是明文传输,https是加密的安全传输;
- 连接的端口不一样,http是80,https是443;
- http连接很简单,没有状态;https是ssl加密的传输,身份认证的网络协议,相对http传输比较安全。
对称加密和非对称加密
- 对称加密: 加密和解密的秘钥使用的是同一个
- 特点:密钥较短,破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,且对计算机性能要求也没有那么高。
- 优点:算法公开、计算量小、加密速度快、加密效率高
- 缺点
- 在数据传送前,发送方和接收方必须商定好秘钥,然后使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。
- 每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。
- 常见的对称加密算法:DES、IDEA、RC4、RC5、RC6、3DES、Blowfish 和 AES
- 非对称加密:非对称加密算法需要两个密钥:公开密钥和私有密钥。
- 定义:公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
- 实现机密信息交换的基本过程:甲方生成一对密钥并将其中的一把作为公有密钥向其它方公开,得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方,甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。
- 优点:安全
- 缺点:速度慢
- 常见的非对称加密算法:RSA(CA证书)、DSA(数字签名用)、ECC(移动设备用)、Diffie-Hellman、El Gamal
- Hash算法(摘要算法)
- Hash算法特别的地方在于它是一种单向算法,用户可以通过hash算法对目标信息生成一段特定长度的唯一hash值,却不能通过这个hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。
- 常见的摘要算法有:MD2、MD4、MD5、HAVAL、SHA
Https建立连接流程
https://www.cnblogs.com/xiaonian8/p/13761230.html
SSL加密过程
SSL会话主要分为三步:
- 客户端向服务器端索要并验证证书;
- 双方协商生成"会话密钥";对称密钥
- 双方采用"会话密钥"进行加密通信;
https://zhuanlan.zhihu.com/p/143347041
为什么数据传输是用对称加密?
- 非对称加密的加解密效率是非常低的,而 http 的应用场景中通常端与端之间存在大量的交互,非对称加密的效率是无法接受的。
- 在 HTTPS 的场景中只有服务端保存了私钥,一对公私钥只能实现单向的加解密,所以 HTTPS 中内容传输加密采取的是对称加密,而不是非对称加密。
浏览器如何验证证书的合法性?
- 验证域名、有效期等信息是否正确:证书上都有包含这些信息,比较容易完成验证;
- 判断证书来源是否合法:每份签发证书都可以根据验证链查找到对应的根证书,操作系统、浏览器会在本地存储权威机构的根证书,利用本地根证书可以对对应机构签发证书完成来源验证
- 判断证书是否被篡改:需要与 CA 服务器进行校验;
- 判断证书是否已吊销:通过CRL(Certificate Revocation List 证书注销列表)和 OCSP(Online Certificate Status Protocol 在线证书状态协议)实现,其中 OCSP 可用于第3步中以减少与 CA 服务器的交互,提高验证效率。
负载均衡
负载均衡(Load balancing)是一种计算机技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。 使用带有负载均衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性。负载均衡服务通常是由专用软件和硬件来完成,主要作用是将大量作业合理地分摊到多个操作单元上进行执行,用于解决互联网架构中的高并发和高可用的问题。一般来说负载均衡分为以下两种:
- 请求负载均衡,即将用户的请求均衡地分发到不同的服务器进行处理。
- 简单轮询
- 加权轮询
- 加权轮询改进(Nginx)
- 随机策略(Dubbo)
- 数据负载均衡,即将用户更新的数据分发到不同的存储服务器。
- 一致性哈希(以及一些改进,比如虚拟节点,有限负载)(Memcache)
- 哈希槽(Redis)
- 基于关键字
如何在我们的项目中选择这些算法呢?其实主要基于如下几个条件:
- 服务器节点的异构性(即各个服务器节点的处理能力)。也就是我们每一个服务器的资源是不同的(可以是算力,可以是存储能力),显然一般的简单轮询无法做到对于拥有不同异构性服务器节点的负载均衡,而加权轮询则可很好的解决这个问题。就这样也可以看出简单轮询其实是适合每个请求的请求资源是相近的。
- 服务器处理请求的开销。我们每一个请求的开销是不同的,如何根据不同的请求选择合适的服务器呢?有两种方法,一种是使用单体调度的思路,即每个从节点会向主节点汇报自己的空闲资源,当请求到来时,主节点通过资源调度算法选择一个合适的从节点来处理该请求;第二种是是使用一致性哈希,从哈希函数上入手,让请求所需的资源和服务器节点的空闲资源与哈希函数挂钩,即通过将资源作为自变量带入哈希函数进行计算,从而映射到哈希环中。当然这一切都需要我们能够计算资源。
- 请求是否有状态(处理请求的过程是否完全依赖于请求)。这其实就是每个请求之间是否有因果关系,典型的就是HTTP的短连接,显然每一个请求只依赖于自己请求的url或者额外数据而与其他http请求无关,这就是典型的无状态请求。这也意味同一个请求可以分布到不同的节点上,这就意味着其适合于轮询,随机这类算法。当遇到有状态的请求时,显然我们需要多个请求落在同一个节点上或者全部节点收敛于一致状态来保证数据一致性。此时我们就可以使用哈希相关的负载均衡算法,当然也有类似于cookie这样的解决方式。
负载均衡反向代理模式
(1)反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
(2)反向代理负载均衡技术是把将来自internet上的连接请求以反向代理的方式动态地转发给内部网络上的多台服务器进行处理,从而达到负载均衡的目的。
(3)反向代理负载均衡能以软件方式来实现,如apache mod_proxy、netscape proxy等,也可以在高速缓存器、负载均衡器等硬件设备上实现。反向代理负载均衡可以将优化的负载均衡策略和代理服务器的高速缓存技术结合在一起,提升静态网页的访问速度,提供有益的性能;由于网络外部用户不能直接访问真实的服务器,具备额外的安全性(同理,NAT负载均衡技术也有此优点)。
(4)其缺点主要表现在以下两个方面:
- 反向代理是处于OSI参考模型第七层应用层,所以就必须为每一种应用服务专门开发一个反向代理服务器,这样就限制了反向代理负载均衡技术的应用范围,现在一般都用于对web服务器的负载均衡。
- 针对每一次代理,代理服务器就必须打开两个连接,一个对外,一个对内,因此在并发连接请求数量非常大的时候,代理服务器的负载也就非常大了,在最后代理服务器本身会成为服务的瓶颈。
一般来讲,可以用它来对连接数量不是特别大,但每次连接都需要消耗大量处理资源的站点进行负载均衡,如search等。
网络编程相关的类
- InteAddress类:InetAddress将IP地址以对象的形式进行封装,可以更方便的操作和获取其属性。
- URL和URLConnection类:通过URL我们可以访问Internet上的各种网络资源,比如最常见的WWW,FTP站点。 URL可以被认为是指向互联网资源的"指针",通过URL可以获得互联网资源相关信息,包括获得URL的InputStream对象获取资源的信息,以及一个到URL所引用远程对象的连接URLConnection。创建一个和URL的连接,需要如下几个步骤:
- 创建URL对象,并通过调用openConnection方法获得URLConnection对象;
- 设置URLConnection参数和普通请求属性;
- 向远程资源发送请求;
- 远程资源变为可用,程序可以访问远程资源的头字段和通过输入流来读取远程资源返回的信息。
- URLDecoder和URLEncoder:这两个类可以别用于将application/x-www-form-urlencoded MIME类型的字符串转换为普通字符串,将普通字符串转换为这类特殊型的字符串。使用URLDecoder类的静态方法decode()用于解码,URLEncoder类的静态方法encode()用于编码。
- Socket和ServerSocket类:Socket通常用来实现客户方和服务方的连接。
- DatagramSocket类:用来支持数据报通信,DatagramSocket用于在程序之间建立传送数据报的通信连接, DatagramPacket则用来表示一个数据报。
WebSocket 长连接实现
WebSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。实时通讯的最优方案。
之前有两个替代方案,不过都不能完全满足需求。一个是轮询,一个是comet。简单理解,轮询就是通过js设置一个定时器不断查询接口,但是这样做会造成一个问题,定时器频率太慢相当于延时会很长,频率太快又会给服务器带来很大的压力;而comet可以理解为一次请求如果没有超过预定时间或者没有返回数据,就会一直保持链接状态,在服务器挂起一个线程,这就代表着也要消耗服务器资源,而且,一个HTTP连接在长时间没有数据传输的情况下,链路上的任何一个网关都可能关闭这个连接,而网关是我们不可控的,这就要求Comet连接必须定期发一些ping数据表示连接"正常工作"。
- 注意事项:
- 正常ajax访问服务器地址可以通过http或https,而WebSocket访问服务器地址要通过ws。
- 可以在通过在地址后面加一个?加其他要传递的参数。类似于get的请求方式。如:ws://127.0.0.1:5000?id=213
- 通过send方法向服务器发送数据时,我们只能传递字符串,所以在发送数据前如果数据结构比较复杂就需要JSON.stringify()方法将参数转为字符串,同时也需要用JSON.parse()方法将服务端发送的数据解析出来。
TCP协议下的socket
Tomcat底层原理
Tomcat通过监听端口,获取数据,然后解析数据,根据请求url找到对应的Servlet实现类,然后通过反射执行Servlet实现类中的方法。
IPv4和IPv6的区别
- 协议地址
- 地址长度
- 地址的表示方法
- 地址配置
- 数据包
- 包的大小
- 包头
- 数据包碎片
- DNS记录
IPv4协议的地址(A)记录,映射主机名;指针(PTR)记录,IN-ADDR.ARPA DNS域。
IPv6协议的地址(AAAA)记录,映射主机名;指针(PTR)记录,IP6.ARPA DNS域
- 地址解析协议
IPv4协议:地址解析协议(ARP)可用于将IPv4地址映射到MAC地址。
IPv6协议:地址解析协议(ARP)被邻居发现协议(NDP)的功能所取代。
- 身份验证和加密
IPv6提供身份验证和加密,但IPv4不提供。
- IPSec支持
IPv4协议的IPSec支持只是可选的。IPv4协议有内置的IPSec支持。
RPC
RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务。一个 RPC 的核心功能主要有 5 个部分组成,分别是:客户端、客户端存根、网络传输模块、服务端存根、服务端等。
- 客户端(Client):服务调用方。
- 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端。
- 服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理。
- 服务端(Server):服务的真正提供者。
- Network Service:底层传输,可以是 TCP 或 HTTP。
图 完整 RPC 架构图
RPC 的核心功能主要由 5 个模块组成,如果想要自己实现一个 RPC,最简单的方式要实现三个技术点,分别是:服务寻址、数据流的序列化和反序列化、网络传输。
在 RPC 中可选的网络传输方式有多种,可以选择 TCP 协议、UDP 协议、HTTP 协议。
- 基于 TCP 的协议实现的 RPC 调用,由于 TCP 协议处于协议栈的下层,能够更加灵活地对协议字段进行定制,减少网络开销,提高性能,实现更大的吞吐量和并发数。但是需要更多关注底层复杂的细节,实现的代价更高。同时对不同平台,如安卓,iOS 等,需要重新开发出不同的工具包来进行请求发送和相应解析,工作量大,难以快速响应和满足用户需求。
- 基于 HTTP 协议实现的 RPC 则可以使用 JSON 和 XML 格式的请求或响应数据。而 JSON 和 XML 作为通用的格式标准,开源的解析工具已经相当成熟,在其上进行二次开发会非常便捷和简单。但是由于 HTTP 协议是上层协议,发送包含同等内容的信息,使用 HTTP 协议传输所占用的字节数会比使用 TCP 协议传输所占用的字节数更高。此在同等网络下,通过 HTTP 协议传输相同内容,效率会比基于 TCP 协议的数据效率要低,信息传输所占用的时间也会更长,当然压缩数据,能够缩小这一差距。
- 基于消息队列的RPC异步调用
webService、webSocket、socket、http之间的区别
- HTTP
HTTP 是基于请求响应式的,即通信只能由客户端发起,服务端做出响应,无状态,无连接。无状态指每次连接只处理一个请求,请求结束后断开连接。无连接指对于事务处理没有记忆能力,服务器不知道客户端是什么状态。以往实现即时通讯的手段:
- 轮询:客户端定时向服务器发送 Ajax 请求,服务器接到请求后马上返回响应信息并关闭连接。
- 长轮询:客户端向服务器发送 Ajax 请求,服务器接到请求后 hold 住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
- 长连接:在页面里嵌入一个隐蔵 iframe,将这个隐蔵 iframe 的 src 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。
- Flash Socket:在页面中内嵌入一个使用了 Socket 类的 Flash 程序 JavaScript 通过调用此 Flash 程序提供的 Socket 接口与服务器端的 Socket 接口进行通信,JavaScript 在收到服务器端传送的信息后控制页面的显示。
- webSocket
为什么需要webSocket,HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。
WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
其他特点包括:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
- WebSocket与HTTP的关系
- 相同点
- Websocket使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket协议使用80端口;运行在TLS之上时,默认使用443端口。
- 都是一样基于TCP的,都是可靠性传输协议。
- 都是应用层协议。
- 不同点
- WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
- WebSocket是需要握手进行建立连接的。
- 联系
WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
- Socket
Socket 是操作系统提供的对于传输层(TCP / UDP)抽象的接口,是一个编程概念,而 Websocket 与 HTTP 一样是一个成文的互联网协议。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。
- webService
WebService是一种跨编程语言和跨操作系统平台的远程调用技术。跨编程语言和跨操作平台就是说服务端程序采用java编写,客户端程序则可以采用其他编程语言编写,反之亦然!跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上运行。
远程调用:就是一台计算机a上的一个程序可以调用到另外一台计算机b上的一个对象的方法,譬如,银联提供给商场的pos刷卡系统,商场的POS机转账调用的转账方法的代码其实是跑在银行服务器上。再比如,amazon,天气预报系统,淘宝网,校内网,百度等把自己的系统服务以webservice服务的形式暴露出来,让第三方网站和程序可以调用这些服务功能,这样扩展了自己系统的市场占有率,往大的概念上吹,就是所谓的SOA应用。
从表面上看,WebService就是一个应用程序向外界暴露出一个能通过Web进行调用的API,把调用这个WebService的应用程序叫做客户端,而把提供这个WebService的应用程序叫做服务端。从深层次看,WebService是建立可互操作的分布式应用程序的新平台,是一个平台,是一套标准。
WebService平台需要一套协议来实现分布式应用程序的创建。任何平台都有它的数据表示方法和类型系统。要实现互操作性,WebService平台必须提供一套标准的类型系统,用于沟通不同平台、编程语言和组件模型中的不同类型系统。Web service平台必须提供一种标准来描述Web service,让客户可以得到足够的信息来调用这个Web service。最后,我们还必须有一种方法来对这个Web service进行远程调用,这种方法实际是一种远程过程调用协议(RPC)。为了达到互操作性,这种RPC协议还必须与平台和编程语言无关。
- WebService平台技术
XML+XSD,SOAP和WSDL就是构成WebService平台的三大技术。
- XML
WebService采用HTTP协议传输数据,采用XML格式封装数据(即XML中说明调用远程服务对象的哪个方法,传递的参数是什么,以及服务对象的返回结果是什么)。XML是WebService平台中表示数据的格式。除了易于建立和易于分析外,XML主要的优点在于它既是平台无关的,又是厂商无关的。无关性是比技术优越性更重要的:软件厂商是不会选择一个由竞争对手所发明的技术的。
- XML Schema(XSD)
XML解决了数据表示的问题,但它没有定义一套标准的数据类型,更没有说怎么去扩展这套数据类型。例如,整型数到底代表什么?16位,32位,64位?这些细节对实现互操作性很重要。XML Schema(XSD)定义了一套标准的数据类型,并给出了一种语言来扩展这套数据类型。WebService平台就是用XSD来作为其数据类型系统的。当你用某种语言(如VB.NET或C#)来构造一个Web service时,为了符合WebService标准,所有你使用的数据类型都必须被转换为XSD类型。你用的工具可能已经自动帮你完成了这个转换,但你很可能会根据你的需要修改一下转换过程。
- SOAP(Simple Object Access Protocol简单对象访问协议)
WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。SOAP提供了标准的RPC方法来调用Web Service。SOAP协议 = HTTP协议 + XML数据格式,SOAP协议定义了SOAP消息的格式,SOAP协议是基于HTTP协议的,SOAP也是基于XML和XSD的,XML是SOAP的数据编码方式。打个比喻:HTTP就是普通公路,XML就是中间的绿色隔离带和两边的防护栏,SOAP就是普通公路经过加隔离带和防护栏改造过的高速公路。
- WSDL
好比我们去商店买东西,首先要知道商店里有什么东西可买,然后再来购买,商家的做法就是张贴广告海报。 WebService也一样,WebService客户端要调用一个WebService服务,首先要有知道这个服务的地址在哪,以及这个服务里有什么方法可以调用,所以,WebService务器端首先要通过一个WSDL文件来说明自己家里有啥服务可以对外调用,服务是什么(服务中有哪些方法,方法接受的参数是什么,返回值是什么),服务的网络地址用哪个url地址表示,服务通过什么方式来调用。
WSDL(Web Services Description Language)就是这样一个基于XML的语言,用于描述Web Service及其函数、参数和返回值。它是WebService客户端和服务器端都能理解的标准格式。因为是基于XML的,所以WSDL既是机器可阅读的,又是人可阅读的,这将是一个很大的好处。一些最新的开发工具既能根据你的Web service生成WSDL文档,又能导入WSDL文档,生成调用相应WebService的代理类代码。
WSDL文件保存在Web服务器上,通过一个url地址就可以访问到它。客户端要调用一个WebService服务之前,要知道该服务的WSDL文件的地址。WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址:1.注册到UDDI服务器,以便被人查找;2.直接告诉给客户端调用者。
WSDL
WSDL(Web Services Description Language),web服务描述语言,是webservice服务端使用说明书,说明服务端接口、方法、参数和返回值,WSDL是随服务发布成功,自动生成,无需编写。
- 文档结构
- Service:相关端口的集合,包括其关联的接口、操作、消息等。
- Binding:特定端口类型的具体协议和数据格式规范
- portType: 服务端点,描述 web service可被执行的操作方法,以及相关的消息,通过binding:指向portType
- message: 定义一个操作(方法)的数据参数
- types: 定义 web service 使用的全部数据类型
- 阅读方式(从下往上)
- 先看service标签,看相应port的binding属性,然后通过值查找上面的binding标签。
- 通过binding标签可以获得具体协议等信息,然后查看binding的type属性
- 通过binding的type属性,查找对应的portType,可以获得可操作的方法和参数、返回值等。
- 通过portType下的operation标签的message属性,可以向上查找message获取具体的数据参数信息。
Java WebService规范
Java 中共有三种WebService 规范,分别是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。
- JAX-WS
JAX-WS(Java API For XML-WebService)。早期的基于SOAP 的JAVA 的Web 服务规范JAX-RPC(java API For XML-Remote Procedure Call)目前已经被JAX-WS 规范取代,JAX-WS 是JAX-RPC 的演进版本,但JAX-WS 并不完全向后兼容JAX-RPC,二者最大的区别就是RPC/encoded 样式的WSDL,JAX-WS 已经不提供这种支持。JAX-RPC 的API 从JAVA EE5 开始已经移除,如果你使用J2EE1.4,其API 位于javax.xml.rpc.包。JAX-WS(JSR 224)规范的API 位于javax.xml.ws.包,其中大部分都是注解,提供API 操作Web 服务(通常在客户端使用的较多,由于客户端可以借助SDK 生成,因此这个包中的API 我们较少会直接使用)。
- JAXM&SAAJ
JAXM(JAVA API For XML Message)主要定义了包含了发送和接收消息所需的API,相当于Web 服务的服务器端,其API 位于javax.messaging.*包,它是Java EE 的可选包,因此你需要单独下载。
SAAJ(SOAP With Attachment API For Java,JSR 67)是与JAXM 搭配使用的API,为构建SOAP 包和解析SOAP 包提供了重要的支持,支持附件传输,它在服务器端、客户端都需要使用。这里还要提到的是SAAJ 规范,其API 位于javax.xml.soap.*包。
JAXM&SAAJ 与JAX-WS 都是基于SOAP 的Web 服务,相比之下JAXM&SAAJ 暴漏了SOAP更多的底层细节,编码比较麻烦,而JAX-WS 更加抽象,隐藏了更多的细节,更加面向对象,实现起来你基本上不需要关心SOAP 的任何细节。那么如果你想控制SOAP 消息的更多细节,可以使用JAXM&SAAJ。
- JAX-RS
JAX-RS 是JAVA 针对REST(Representation State Transfer)风格制定的一套Web 服务规范,由于推出的较晚,该规范(JSR 311,目前JAX-RS 的版本为1.0)并未随JDK1.6 一起发行。
WebService入门案例
- 服务端实现
第一步:编写SEI(Service Endpoint Interface),SEI在webservice中称为portType,在java中就是普通接口 public interface WeatherInterface { public String queryWeather(String cityName); }
第二步:编写SEI实现类,此类作为webservice提供服务类 @WebService //表示该类是一个服务类,需要发布其中的public的方法 public class WeatherInterfaceImpl implements WeatherInterface { @Override public String queryWeather(String cityName) { System.out.println("获取城市名"+cityName); String weather = "暴雨"; return weather; } }
第三步:发布服务,Endpoint类发布服务,publish方法,两个参数:1.服务地址;2.服务实现类 public class WeatherServer { public static void main(String[] args) { Endpoint.publish("http://127.0.0.1:12345/weather", new WeatherInterfaceImpl()); } }
第四步:测试服务是否发布成功,通过阅读wsdl,确定客户端调用的接口、方法、参数和返回值存在,证明服务发布成功 //我们在浏览器输入 http://127.0.0.1:12345/weather?wsdl,只要能获取到,就能确定WebService服务发布成功 |
- 客户端实现
//客户端调用服务有很多种方法,我们先用工具生成客户端代码:wsimport是jdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码)。当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码。 第一步:创建一个客户端空项目,cmd命令行进入此项目的src目录,cmd中使用以下命令生成客户端代码:wsimport -s . http://127.0.0.1:12345/weather?wsdl -s是指编译出源代码文件,后面的.(点)指將代码放到当前目录下。最后面的http….是指获取wsdl说明书的地址
第二步:查看wsdl获取接口信息
第三步:编写客户端 public class WeatherClient { public static void main(String[] args) { //创建服务视图,视图是从wsdl文件的service标签的name属性获取 WeatherInterfaceImplService weatherInterfaceImplService = new WeatherInterfaceImplService(); //获取服务实现类,实现类从wsdl文件的portType的name属性获取 WeatherInterfaceImpl weatherInterfaceImpl = weatherInterfaceImplService.getPort(WeatherInterfaceImpl.class); //获取查询方法,从portType的operation标签获取 String weather = weatherInterfaceImpl.queryWeather("北京"); System.out.println(weather); } } |
浙公网安备 33010602011771号