1、select poll epoll区别
select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:
1、 单个进程可监视的fd数量被限制,即能监听端口的大小有限。
2、 对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低
当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成相关操作,那就避免了轮询,这正是epoll与kqueue做的。
3、需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。
poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个过程经历了多次无谓的遍历。它没有最大连接数的限制,原因是它是基于链表来存储的,但是同样有一个缺点:
1、大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。
2、poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。
epoll有EPOLLLT和EPOLLET两种触发模式,LT是默认的模式,ET是“高速”模式。LT模式下,只要这个fd还有数据可读,每次 epoll_wait都会返回它的事件,提醒用户程序去操作,而在ET(边缘触发)模式中,它只会提示一次,直到下次再有数据流入之前都不会再提示了,无论fd中是否还有数据可读。所以在ET模式下,read一个fd的时候一定要把它的buffer读光,也就是说一直读到read的返回值小于请求值,或者 遇到EAGAIN错误。epoll将文件描述符拷贝到内核空间后使用红黑树进行维护,同时向内核注册每个文件描述符的回调函数,当某个文件描述符可读可写的时候,将这个文件描述符加入到就绪链表里,并唤起进程,返回就绪链表到用户空间。内部通过红黑树和双向链表实现。
区别:
1、操作方式及效率:select是遍历,需要遍历fd_set每一个比特位(= MAX_CONN),O(n);poll是遍历,但只遍历到pollfd数组当前已使用的最大下标(≠ MAX_CONN),O(n);epoll是回调,O(1)
2、最大连接数:
select为1024/2048(一个进程打开的文件数是有限制的);poll无上限;epoll无上限。
3、fd拷贝:
select每次都需要把fd集合从用户态拷贝到内核态;poll每次都需要把fd集合从用户态拷贝到内核态;epoll调用epoll_ctl时拷贝进内核并放到事件表中,但用户进程和内核通过mmap映射共享同一块存储,避免了fd从内核赋值到用户空间。
4、其他:
select每次内核仅仅是通知有消息到了需要处理,具体是哪一个需要遍历所有的描述符才能找到。epoll不仅通知有I/O到来还可通过callback函数具体定位到活跃的socket,实现伪AIO。
应用场景
很容易产生一种错觉认为只要用 epoll 就可以了,select 和 poll 都已经过时了,其实它们都有各自的使用场景。
- select 应用场景
select 的 timeout 参数精度为 1ns,而 poll 和 epoll 为 1ms,因此 select 更加适用于实时性要求比较高的场景,比如核反应堆的控制。select 可移植性更好,几乎被所有主流平台所支持。 - poll 应用场景
poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。 - epoll 应用场景
只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接。
需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。
需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且epoll 的描述符存储在内核,不容易调试。
2、web访问网页全过程
- 域名解析成IP地址;
- 与目的主机进行TCP连接(三次握手);
- 发送与收取数据(浏览器与目的主机开始HTTP访问过程);
- 目的主机断开TCP连接(四次挥手);
参考链接
3、TIMEWAIT为什么要等待2MSL:
第一,为了保证A发送的最后一个ACK报文能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后就立即释放连接,就无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。这样,B就无法按照正常的步骤进入CLOSED状态。
第二,A在发送完ACK报文段后,再经过2MSL时间,就可以使本连接持续的时间所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求的报文段。
4、http和https
HTTP属于超文本传输协议,用来在Internet上传送超文本,而HTTPS为安全超文本传输协议,在HTTPS基础上拥有更强的安全性,简单来说HTTPS是HTTP的安全版,是使用TLS/SSL加密的HTTP协议。
https 协议需要到 ca 申请证书,目前市面上的免费证书也不少,收费的也都比较贵。http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协议。
http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
http 的连接很简单,是无状态的。
HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全。
5、get和post方式的区别:
概括
- 对于GET方式的请求,浏览器会把http
header和data一并发送出去,服务器响应200(返回数据); - 而对于POST,浏览器先发送header,服务器响应100
continue,浏览器再发送data,服务器响应200 ok(返回数据)
区别: - 1、get参数通过url传递,post放在requestbody中。
- 2、get请求在url中传递的参数是有长度限制的,而post没有。
- 3、get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。
- 4、get请求只能进行url编码,而post支持多种编码方式。
- 5、get请求会浏览器主动cache,而post支持多种编码方式。
- 6、get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留。
- 7、post用于修改和写入数据,get一般用于搜索排序和筛选之类的操作。
- 8、GET产生一个TCP数据包;POST产生两个TCP数据包,在真正接收数据之前会先将请求头发送给服务器进行确认,然后才真正发送数据。
GET优势:比较快,且不改变服务器状态,是幂等的。同时浏览器可以对GET进行缓存,下次直接读缓存即可。POST发两次比较慢,且包含更多的请求头。参考
6、HTTP/1.0和1.1的区别:
1.0每请求一个文档就要有两倍RTT的开销(TCP连接),而1.1使用了持续连接,万维网服务器在发送响应后仍然在一段时间内保持这种连接。
7、ip地址的正则表达式
8、tcp滑动窗口原理
本质上是描述接收方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据,如果发送方收到接收方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接收方发送窗口大小不为0的数据报的到来。
9、ARP协议
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息。
10、DNS:域名解析协议
浏览器先检查自身缓存中有没有被解析过的这个域名对应的ip地址,如果浏览器缓存中没有(专业点叫还没命中),浏览器会检查操作系统缓存中有没有对应的已解析过的结果。如果至此还没有命中域名,才会真正的请求本地域名服务器(LDNS)来解析这个域名。如果LDNS仍然没有命中,就直接跳到Root Server 域名服务器请求解析。根域名服务器返回给LDNS一个所查询域的主域名服务器(gTLD Server)地址。
DNS解析有两种方式:递归查询和迭代查询
- 递归查询 用户先向本地域名服务器查询,如果本地域名服务器的缓存没有IP地址映射记录,就向根域名服务器查询,根域名服务器就会向顶级域名服务器查询,顶级域名服务器向权限域名服务器查询,查到结果后依次返回。
- 迭代查询 用户向本地域名服务器查询,如果没有缓存,本地域名服务器会向根域名服务器查询,根域名服务器返回顶级域名服务器的地址,本地域名服务器再向顶级域名服务器查询,得到权限域名服务器的地址,本地域名服务器再向权限域名服务器查询得到结果
参考链接
11、http换行符的作用
对于HTTP请求格式来说,头部和主体内容之间有一个回车换行符(CRLF)是相当重要的。CRLF告诉HTTP服务器主体内容是在什么地方开始的。在一些互联网编程书籍中,CRLF还被认为是HTTP请求的第四部分。不同操作系统的换行符不一样。
12、listen是阻塞的吗
listen 会立刻返回,accept 才会造成阻塞。
13、怎么判断服务器端关闭
如果在正常通信中,服务器关闭了连接那么客户端会收到正常的EOF,如果对这个连接用epoll或者select进行监听,可以马上得知服务器关闭了连接。否则就定时向服务器发心跳探测,不然是不太可能得知服务器目前的状态的。之所以你现在不会立刻发现问题是因为服务器退出后,客户端需要靠下一次send才会触发问题,因为这时候连接已关闭,而客户端继续写,会产生SIGPIPE异常,而这个异常的默认动作是进程终止,所以你的客户端退出了。
14、怎么判断客户器端关闭
- 服务器需要知道客户端主机是否已崩溃并且关闭,或者崩溃但重启。许多实现提供了存活定时器来完成这个任务。
- SO_KEEPALIVE 机制:这是socket库提供的功能,设置接口是setsockopt API。 默认设置是空闲2小时才发送一个“保持存活探测分节”,不能保证实时检测! 当然也可以修改时间间隔参数,但是会影响到所有打开此选项的套接口!
15、如果发送了紧急指针,服务端会做出什么反应
- TCP协议栈也会为每个套接字维护一个接收端紧急模式标志和一个接收端紧急指针。一旦接收到一个URG标志的数据分段,则TCP接收端会开启此接收端紧急模式标志,并保存接收端紧急指针,并且此刻,其将通知接收进程(发送信号SIGURG,或者给阻塞的select调用返回异常)。
- 在接收端紧急模式下,TCP会监视此后接收到的每个数据分段,如果其中包含之前接收端紧急指针的字节,那么默认情况下,此字节将放在单独的带外缓冲中(独立于接收缓冲区)。如果接收端对套接字调用setsockopt开启了SO_OOBINLINE,此字节将混在普通数据中,称为在线接收。其由接收端紧急指针(大多数实现需要减1)指示,称之为OOB字节。
- 只有在下一个待读字节越过OOB字节之后,也即sockatmark返回0之后,接收端紧急模式才被解除。接收进程只会在进入接收端紧急模式的一刻,才会接收到SIGURG信号,但是在紧急模式下,所有的select都将返回异常。
参考
16、TCP粘包原理、解决
1、TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。
2、原因:
- 发送端:TCP默认使用Nagle算法(主要作用:减少网络中报文段的数量),而Nagle算法主要做两件事:只有上一个分组得到确认,才会发送下一个分组;收集多个小分组,在一个确认到来时一起发送。
- 接收端:如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。
3、解决方法
- 发送方造成的粘包问题,可以通过关闭Nagle算法来解决。
- 接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。应用层上循环处理,应用程序从接收缓存中读取分组时,读完一条数据,就应该循环读取下一条数据,直到所有数据都被处理完成。
- 但是如何判断每条数据的长度呢?可以发送每条数据时,将数据的长度一并发送,例如规定数据的前4位是数据的长度,应用层在处理时可以根据长度来判断每个分组的开始和结束位置。
4、UDP会不会粘包:UDP则是面向消息传输的,是有保护消息边界的,接收方一次只接受一条独立的信息,所以不存在粘包问题。
17、recv返回值
- 默认 socket 是阻塞的,解阻塞与非阻塞recv返回值没有区分,都是 <0 出错 =0 连接关闭 >0 接收到数据大小。
- 失败返回-1。全局变量errno被设为某个值。
- 特别地:返回值<0时并且(errno == EINTR || errno ==EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的,继续接收。
18、HTTP1.0、1.1、2.0的区别
- 长连接:在HTTP/1.0中,默认使用的是短连接,也就是说每次请求都要重新建立一次连接。HTTP 是基于TCP/IP协议的,每一次建立或者断开连接都需要三次握手四次挥手的开销,如果每次请求都要这样的话,开销会比较大。因此最好能维持一个长连接,可以用个长连接来发多个请求。HTTP 1.1起,默认使用长连接。需要将HTTP 的头部,Connection设置为 keep-alive。
- HTTP1.1中新增了24个错误状态响应码。
- HTTP1.1支持只发送header信息(不带任何body信息)。
- HTTP2.0使用多路复用技术(Multiplexing),多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。HTTP/2 使用“HPACK”算法压缩头部信息,消除冗余数据节约带宽。消息不再是“Header+Body”的形式,而是分散为多个二进制“帧”。使用虚拟的“流”传输消息,解决了困扰多年的“队头阻塞”问题,同时实现了“多路复用”,提高连接的利用率。
19、SSH
- SSH是一种网络协议,用于计算机之间的加密登录。如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露。
- SSH之所以能够保证安全,原因在于它采用了公钥加密。
整个过程是这样的:(1)远程主机收到用户的登录请求,把自己的公钥发给用户。(2)用户使用这个公钥,将登录密码加密后,发送回来。(3)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。 - 如果攻击者插在用户与远程主机之间(比如在公共的wifi区域),用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)
- 解决:需要依靠密匙,也就是你必须为自己创建一对密匙,并把公用密匙放在需要访问的服务器上。如果你要连接到SSH服务器上,客户端软件就会向服务器发出请求,请求用你的密匙进行安全验证。服务器收到请求之后,先在该服务器上你的主目录下寻找你的公用密匙,然后把它和你发送过来的公用密匙进行比较。如果两个密匙一致,服务器就用公用密匙加密“质询”(challenge)并把它发送给客户端软件。客户端软件收到“质询”之后就可以用你的私人密匙解密再把它发送给服务器。
- 免密方法:
20、HTTPS的连接过程
- 客户端向服务器发送请求,同时发送客户端支持的一套加密规则(包括对称加密、非对称加密、摘要算法);
- 服务器从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥(用于非对称加密),以及证书的颁发机构等信息(证书中的私钥只能用于服务器端进行解密);
- 客户端验证服务器的合法性,包括:证书是否过期,CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配;
- 如果证书受信任,或者用户接收了不受信任的证书,浏览器会生成一个随机密钥(用于对称算法),并用服务器提供的公钥加密(采用非对称算法对密钥加密);使用Hash算法对握手消息进行摘要计算,并对摘要使用之前产生的密钥加密(对称算法);将加密后的随机密钥和摘要一起发送给服务器;
- 服务器使用自己的私钥解密,得到对称加密的密钥,用这个密钥解密出Hash摘要值,并验证握手消息是否一致;如果一致,服务器使用对称加密的密钥加密握手消息发给浏览器;
- 浏览器解密并验证摘要,若一致,则握手结束。之后的数据传送都使用对称加密的密钥进行加密。
21、reactor模型
22、HTTP大数据量传输
- 分块传输:在响应头里面用文字段“Transfer-Encoding: chunked”来表示body部分分成了许多块进行逐个发送。注意:chunk方式仍然是一个请求内发生的事情。
- 范围请求:HTTP支持范围请求,只要用于允许请求段在请求头里面使用专用的字段只获取文件的一部分。相同于从请求方开始的”化整为零“。
- 参考
23、MSS
最大消息长度(max segment size):TCP在传送大量数据时,是以MSS的大小将数据进行分割发送。重发也是以MSS为单位。
MSS是在三次握手的时候,在两端主机之前被计算得出。连接时会在TCP首部中写入MSS选项,告诉对方自己接口所适应的大小,然后选择一个较小的值投入使用。
24、窗口控制和重发控制
窗口控制的好处:某些确认应答即便丢失,如果后面的确认应答可以覆盖,也无需重发。
重发控制:当某一报文段丢失时,同一个序号的确认应答将会被重复不断的返回。发送端主机如果连续3次收到同一个确认应答,就会将其对应的数据进行重发。这种机制比超时管理更加高效,称作高速重发控制。
25、提高网络利用率
- nagle算法:即使有应该发送的数据,如果数据很少则延迟发送。满足两个条件其一则发送:已发送出局都已经收到确认应答;可以发送最大段长度(MSS)的数据时。
- 延迟确认应答:在没有收到2*最大段长度的数据为止并不返回应答;其他情况下,最大延迟0.5秒确认应答。
- 捎带应答:同一个TCP包中既发送数据又发送确认应答的一种机制。
26、中间人攻击
如图所示:
SSL 证书欺骗攻击流程大概如下:
- 截获客户端与服务器通信的通道
- 然后在 SSL 建立连接的时候,进行中间人攻击
- 将自己伪装成客户端,获取到服务器真实有效的 CA 证书(非对称加密的公钥)
- 将自己伪装成服务器,获取到客服端的之后通信的密钥(对称加密的密钥)
- 有了证书和密钥就可以监听之后通信的内容了
27、为何TCP采用随机序列号
- 防止接受网络上粘滞的TCP包,如果都从0开始的话,极其容易接受之前断开连接发送的粘滞包。虽然可以采用每次TCP会话都使用一个UUID作为标记,但是考虑到每次都要携带UUID,比较浪费流量,所以就采用随机序列号的方法。
- 防止Hack猜测序列号,然后伪装TCP报文,当然这种防御其实很弱。
28、TCP快速重传为什么是三次冗余ack
主要的考虑还是要区分包的丢失是由于链路故障还是乱序等其他因素引发。两次duplicated ACK时很可能是乱序造成的!三次duplicated ACK时很可能是丢包造成的!四次duplicated ACK更更更可能是丢包造成的!但是这样的响应策略太慢。丢包肯定会造成三次duplicated ACK!综上是选择收到三个重复确认时窗口减半效果最好,这是实践经验。参考
29、dns是tcp还是udp
DNS 可以使用 UDP 或者 TCP 进行传输,使用的端口号都为 53。大多数情况下 DNS 使用 UDP 进行传输,这就要求域名解析器和域名服务器都必须自己处理超时和重传从而保证可靠性。在两种情况下会使用 TCP 进行传输:
- 如果返回的响应超过的 512 字节(UDP 最大只支持 512 字节的数据)。
- 区域传送(区域传送是主域名服务器向辅助域名服务器传送变化的那部分数据)。
30、ftp
FTP 使用 TCP 进行连接,它需要两个连接来传送一个文件:
- 控制连接:服务器打开端口号 21 等待客户端的连接,客户端主动建立连接后,使用这个连接将客户端的命令传送给服务器,并传回服务器的应答。
- 数据连接:用来传送一个文件数据。
根据请求方的不同,分为主动和被动模式。
31、常用端口
32、动态主机配置协议
DHCP (Dynamic Host Configuration Protocol) 提供了即插即用的连网方式,用户不再需要手动配置 IP 地址等信息。
DHCP 配置的内容不仅是 IP 地址,还包括子网掩码、网关 IP 地址。DHCP 工作过程如下:
- 客户端发送 Discover 报文,该报文的目的地址为255.255.255.255:67,源地址为 0.0.0.0:68,被放入 UDP中,该报文被广播到同一个子网的所有主机上。如果客户端和 DHCP 服务器不在同一个子网,就需要使用中继代理。
- DHCP 服务器收到 Discover 报文之后,发送 Offer 报文给客户端,该报文包含了客户端所需要的信息。因为客户端可能收到多个 DHCP 服务器提供的信息,因此客户端需要进行选择。
- 如果客户端选择了某个 DHCP 服务器提供的信息,那么就发送 Request 报文给该 DHCP 服务器。
- DHCP 服务器发送 Ack 报文,表示客户端此时可以使用提供给它的信息。
33、uri
34、缓存
优点:
- 缓解服务器压力;
- 降低客户端获取资源的延迟:缓存通常位于内存中,读取缓存的速度更快。并且缓存服务器在地理位置上也有可能比源服务器来得近,例如浏览器缓存。
缺点:
- 让代理服务器进行缓存;
- 让客户端浏览器进行缓存。
35、服务器项目的一些问题
- 如果对端传数据传的很慢,那么用非阻塞epoll是不是就读到不完整的请求了?是的,改用lt模式可以解决
- 如果读的文件非常大,write返回0,但是文件还没写完怎么办,怎么办?(改用阻塞的话,tcp会自动阻塞直到可以发出。继续用非阻塞的话,服务端就要判断返回eagain的时候是否已经发送完成了,客户端方面可以使用Content-type,表示文件总大小)
36、服务器发现
- 服务通常需要调用其他服务。单体应用中,服务通过语言级别的方法或者过程调用另外的服务。在传统的分布式部署中,服务运行在固定,已知的地址(主机和端口),因此可以请求的通过HTTP/REST或其他RPC机制调用。然而,一个现代的微服务应用通常运行在虚拟或者容器环境,服务实例数和它们的地址都在动态改变。
- 当对一个服务发起请求时,客户端对运行在一个已知地址的路由(也叫做负载均衡)发起请求。路由查询服务注册中心,可能构建在路由内,将请求转发给可用的服务实例。
37、TCP序列号超过最大值怎么办
tcp协议头中有seq和ack_seq两个字段,分别代表序列号和确认号。tcp协议通过序列号标识发送的报文段。seq的类型是__u32,当超过__u32的最大值时,会回绕到0。
解决:判断(__s32)(seq1-seq2)<0就可以判断seq1<seq2。这里的__s32是有符号整型的意思,而__u32则是无符号整型。参考。
38、TCP服务器关闭情况
- 正常关闭:客户端close,fd不可读之后发送FIN,服务端回应。服务器fd失效后进行后两次挥手。
- 服务器关机、断电:客户端重传直到超时或是路由服务认为不可达为止。
- 服务器进程结束:返回RST。
- 服务器重启:返回RST,之后重新建立链接。
39、摘要、数字签名、数字证书
A给B发送Email:
- A先对这封Email执行哈希运算得到hash值简称“摘要”,取名h1
- 然后用自己私钥对摘要加密,生成的东西叫“数字签名”
- 把数字签名加在Email正文后面,一起发送给B 防止邮件被窃听你可以用继续B公钥加密
- B收到邮件后使用B私钥对报文解密,用A的公钥对数字签名解密,成功则代表Email确实来自A,失败说明有人冒充
- B对邮件正文执行哈希运算得到hash值,取名h2
- B会对比数字签名的hash值h1和自己运算得到的h2,一致则说明邮件未被篡改。
- 数字证书:明文和数字签名共同组成了数字证书。权威CA使用私钥将网站A的信息和消息摘要(签名S)进行加密打包形成数字证书。公钥给客户端。
40、SYN攻击
应对方法:net.ipv4.tcp_syncookies = 1
- 当 「 SYN 队列」满之后,后续服务器收到 SYN 包,不进入「 SYN 队列」;
- 计算出一个 cookie 值,再以 SYN + ACK 中的「序列号」返回客户端;主要就是对序列号做处理,使其保存客户端的四元组信息(源ip,目标ip,源端口,目的端口)和时间戳,参考。
- 服务端接收到客户端的应答报文时,服务器会检查这个 ACK 包的合法性。如果合法,直接放入到「 Accept 队列」。
- 最后应用通过调用 accpet() socket 接口,从「 Accept 队列」取出的连接。
或者是:net.ipv4.tcp_abort_on_overflow
超出处理能时,对新的 SYN 直接回 RST,丢弃连接。
41、服务端 TIME_WAIT 状态过多
- 原因:存在大量的TCP短连接或者是高并发场景。
- 如下的 Linux 内核参数开启后,则可以复用处于 TIME_WAIT 的 socket 为新的连接所用。net.ipv4.tcp_tw_reuse = 1,net.ipv4.tcp_timestamps=1(默认即为 1),引入了时间戳,我们在前面提到的 2MSL 问题就不复存在了,因为重复的数据包会因为时间戳过期被自然丢弃。
- net.ipv4.tcp_max_tw_buckets:这个值默认为 18000,当系统中处于 TIME_WAIT 的连接一旦超过这个值时,系统就会将所有的 TIME_WAIT 连接状态重置。
- 我们可以通过设置 socket 选项,来设置调用 close 关闭连接行为。如果l_onoff为非 0, 且l_linger值为 0,那么调用close后,会立该发送一个RST标志给对端,该 TCP 连接将跳过四次挥手,也就跳过了TIME_WAIT状态,直接关闭。
42、三次握手四次挥手详细
43、几种IO的区别
1、NIO:需要轮询才知道内核是否已经完成。
2、SIO:内核通知何时可以启动一个IO操作。
3、AIO:内核通知IO操作何时完成。
44、reactor和proactor
- reactor:主线程只负责监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作线程。除此之外,主线程不做任何其他实质性的工作。读写数据,接收新连接、处理客户请求均在工作线程中完成。
- proactor:将所有IO操作交给主线程和内核处理,工作线程仅仅负责业务逻辑。
- 模拟proactor:主线程执行数据读写操作,读写完成之后,主线程向工作线程通知这一完成事件。工作线程获得数据读写的结果,要做的是对读写的结果进行逻辑处理。
45、IP为什么要分片
- 数据链路层具有最大传输单元MTU这个特性,它限制了数据帧的最大长度。通常要传输的IP报文的大小超过最大传输单位MTU时就会产生IP分片情况,IP分片经常发生在网络环境当中。
- 当两台远程PC互联的时候,它们的数据需要穿过很多的路由器和各种各样的网络媒介才能到达对端,网络中不同媒介的MTU各不相同,就好比一长段的水管,由不同粗细的水管组成(MTU不同)通过这段水管最大水量就是由中间最细的水管决定。
- 对于UDP而言,这个协议本身是无连接协议,对数据包的到达顺序以及是否正确到达不甚关心,所以一般UDP应用对分片没有特殊要求。
- 对于TCP而言,这个协议是面向连接的协议,因此它非常在意数据包的到达顺序以及是否传输中有错误发生,因此有些TCP应用对分片有要求。所以TCP在应用层会有MSS分段。
46、本机和本机socket通信
先说结论:不走网卡,不走物理设备,但是走虚拟设备,loopback device环回。
应用层-> socket接口 -> 传输层(tcp/udp报文) -> 网络层 -> back to 传输层 -> backto socket接口 -.> 传回应用程序
47、connect可以非阻塞么
- 可以。
- 可再次调用connect,相应返回失败,如果错误errno是EISCONN,表示socket连接已经建立,否则认为连接失败。
- 或者调用select(),通过FD_ISSET()检查套接口是否可写,确定连接请求是否完成。
48、TCP拥塞控制改进
- TCP中的Reno的快速重传算法是针对一个包的重传情况的,然而在实际中,一个重传超时可能导致许多的数据包的重传,因此当多个数据包从一个数据窗口中丢失时并且触发快速重传和快速恢复算法时,问题就产生了。因此NewReno出现了,它在Reno快速恢复的基础上稍加了修改,可以恢复一个窗口内多个包丢失的情况。具体来讲就是:Reno在收到一个新的数据的ACK时就退出了快速恢复状态了,而NewReno需要收到该窗口内所有数据包的确认后才会退出快速恢复状态,从而更一步提高吞吐量。
- SACK就是改变TCP的确认机制,最初的TCP只确认当前已连续收到的数据,SACK则把乱序等信息会全部告诉对方,从而减少数据发送方重传的盲目性。比如说序号1,2,3,5,7的数据收到了,那么普通的ACK只会确认序列号4,而SACK会把当前的5,7已经收到的信息在SACK选项里面告知对端,从而提高性能,当使用SACK的时候,NewReno算法可以不使用,因为SACK本身携带的信息就可以使得发送方有足够的信息来知道需要重传哪些包,而不需要重传哪些包。
49、close和shutdown区别
- 使用close()时,只有当套接字的引用计数为0的时候才会终止连接
- 用shutdown()就可以直接关闭连接
50、单条记录高并发访问的优化
服务器端:
- 使用缓存,如redis等
- 使用分布式架构进行处理
- 将静态页面和静态资源存储在静态资源服务器,需要处理的数据使用服务器进行计算后返回
- 将静态资源尽可能在客户端进行缓存
- 采用ngnix进行负载均衡
数据库端:
- 数据库采用主从赋值,读写分离措施
- 建立适当的索引
- 分库分表
51、限流算法
漏桶算法:漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。
令牌算法:令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
区别:令牌桶可以用来保护自己,主要用来对调用者频率进行限流,为的是让自己不被打垮。所以如果自己本身有处理能力的时候,如果流量突发(实际消费能力强于配置的流量限制),那么实际处理速率可以超过配置的限制。而漏桶算法,这是用来保护他人,也就是保护他所调用的系统。主要场景是,当调用的第三方系统本身没有保护机制,或者有流量限制的时候,我们的调用速度不能超过他的限制,由于我们不能更改第三方系统,所以只有在主调方控制。这个时候,即使流量突发,也必须舍弃。因为消费能力是第三方决定的。
52、close_wait大量出现
- close_wait状态出现的原因是被动关闭方未关闭socket造成
- 很大可能性是用户服务器的程序实现有问题导致的大量CLOSE_WAIT的socket,比如父进程打开了socket,然后通过fork出子进程来处理业务,父进程继续对网络请求进行监听,永远不会终止;当客户端发FIN过来的时候,处理业务的子进程处理此FIN消息,调用close()对本端进行关闭,然而这个close()调用只是把socket的引用计数器减1,因为父进程还在运行,socket并没关闭,这样就导致系统中又多了一个CLOSE_WAIT的socket,长此以往,就这样了。
- 解决:原因是因为调用ServerSocket类的accept()方法和Socket输入流的read()方法时会引起线程阻塞,所以应该用setSoTimeout()方法设置超时(缺省的设置是0,即超时永远不会发生);超时的判断是累计式的,一次设置后,每次调用引起的阻塞时间都从该值中扣除,直至另一次超时设置或有超时异常抛出。
53、DNS劫持
- DNS劫持 就是通过劫持了 DNS 服务器,通过某些手段取得某域名的解析记录控制权,进而修改此域名的解析结果,导致对该域名的访问由原 IP 地址转入到修改后的指定 IP,其结果就是对特定的网址不能访问或访问的是假网址,从而实现窃取资料或者破坏原有正常服务的目的。DNS劫持 通过篡改 DNS 服务器上的数据返回给用户一个错误的查询结果来实现的。
- 解决:HTTPDNS,绕开传输层的劫持,直接在应用层查找DNS