1、网络编程

讲讲Reactor模型

  一般来说,Reactor模型有三种角色,一个是accptor,一个是reactor,一个是handler。通过acceptor向reactor注册关注的事件,当事件发生时,reactor将事件交给相应的handler处理执行相关业务逻辑。本质上就是将关注的事件与相应回调函数关联,事件发生时执行相应回调函数。
  与Proactor的核心区别就是Reactor处理的是未完成IO的事件,而Proactor处理的是已完成IO的事件或信号。

UDP socket编程主要用到哪些函数

服务端:socket(),bind(),recvfrom(),sendto(),close()
客户端:socket(),sendto(),recvfrom(),close()

UDP的connect函数

  TCP的connect函数用来三次握手建立TCP连接,而UDP的套接字使用connect函数作用仅仅是记录对端的IP和端口号。

TCP中的connect函数

  TCP中的connect函数用于三次握手建立TCP连接。
  阻塞方法:发送SYN报文段,收到SYN,ACK报文段后,发送ACK报文段然后返回。
  非阻塞方法:首先判断返回值,-1的话检查错误码,如果是EINTR,则重新connect,如果是EINPROGRESS,则说明正在连接中,其余错误码则说明连接出现错误。之后使用epoll检查是否有写事件发生(accept检查的是读事件),有的话使用getsockopt检查错误,没有错误则连接建立成功。

read和write

一、read
1、阻塞与非阻塞:
  阻塞的read在有数据时返回,没有数据时阻塞;
  非阻塞的read在没有数据时返回-1,错误码为EAGAIN或EWOULDBLOCK(其实这个就是EAGAIN,数值一样#define EWOULDBLOCK EAGAIN);
2、返回值:
  返回值大于0,正常;
  返回值等于零,读到FIN,一般关闭连接;
  返回值小于零,错误码EINTR表示被信号中断,一般会重新调用read;错误码EAGAIN或EWOULDBLOCK表示当前没有数据。
二、write
1、阻塞与非阻塞:
  阻塞的write在缓冲区空间足以发送所有数据时才返回;
  非阻塞的write在缓冲区空间不够时只写一部分,然后返回写了的长度,之后再调用则返回-1,错误码EAGAIN或EWOULDBLOCK。
2、返回值:
  返回值大于0,正常;
  返回值等于0,套接字已经关闭;
  返回值小于0,错误码EINTR表示被信号中断,一般会重新调用write;错误码EAGAIN或EWOULDBLOCK表示当前缓冲区没有空间。

socket,listen,bind,accept

1、int socket(int domain, int type, int protocol);
domain:协议族,如IPV4,IPV6等
type:socket类型,如SOCK_STREAM(流式套接字TCP)、SOCK_DGRAM(数据报式套接字UDP)。
protocol:协议类型。

2、int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  sockfd:需要绑定端口号和ip的套接字
  addr:指向要绑定给sockfd的协议地址
3、int listen(int sockfd, int backlog);
  sockfd:用于监听的套接字;
  backlog:新连接等待队列的长度

4、int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  sockfd:用于监听的套接字
  addr:对端的协议地址

epoll各事件含义

  可read:EPOLLIN
  可write:EPOLLOUT
  带外数据(紧急数据):EPOLLPRI
  对端正常关闭:触发EPOLLRDHUP和EPOLLIN
  本端发生错误:触发EPOLLHUP和EPOLLERR
  对端异常关闭(如拔网线):不会触发任何事件

EPOLLHUP和EPOLLRDHUP

  EPOLLRDHUP 表示读关闭。不是所有的内核版本都支持。有两种场景:
1、对端发送 FIN (对端调用close 或者 shutdown(SHUT_WR)).
2、本端调用 shutdown(SHUT_RD). 当然,关闭 SHUT_RD 的场景很少。
  EPOLLHUP 表示读写都关闭。
1、本端调用shutdown(SHUT_RDWR)。 不能是close,close 之后,文件描述符已经失效。
2、本端调用 shutdown(SHUT_WR),对端调用 shutdown(SHUT_WR)。

2、TCP/UDP/IP

TCP如何保证可靠性

保证数据没有在传输中变化:校验和
保证数据的送达:序号和确认号,超时重传
保证接收方缓存足够接收数据:流量控制
保证数据发送不引起网络拥堵:拥塞控制算法,包含慢启动,拥塞避免,快恢复
保证连接和断开时的可靠:三次握手,四次挥手

拥塞控制

  慢启动:将拥塞窗口大小设为1个MSS,每个确认报文段到来时,将拥塞窗口大小+1个MSS。该状态拥塞窗口呈指数增大,每个RTT增大一倍。超时时重新开始慢启动,拥塞窗口设为1,收到三个冗余ACK时启动快恢复,拥塞窗口减半,这两种情况将慢启动阈值设为拥塞窗口的一半。当拥塞窗口等于慢启动阈值时进入拥塞避免状态。
  拥塞避免:每过一个RTT将拥塞窗口+1个MSS。超时时重新开始慢启动,拥塞窗口设为1,收到三个冗余ACK时启动快恢复,拥塞窗口减半,这两种情况将慢启动阈值设为拥塞窗口的一半。
  快恢复:实际是相对慢启动而言的,拥塞窗口不是从1开始,而是从当前窗口的一半开始执行拥塞避免算法。

三次握手,四次挥手

  三次握手:客户端首先发送一个SYN报文段,进入SYN_SENT状态,服务端收到后回送一个SYN,ACK报文段,进入SYN_RCVD状态,客户端收到后回送一个ACK报文段同时可以开始发送数据并进入ESTABLISH状态,服务端收到ACK报文段后也进入ESTABLISH状态。
  四次挥手:客户端首先发送一个FIN报文段,进入FIN_WAIT1状态,服务端回送一个ACK报文段进入CLOSE_WAIT状态,客户端收到ACK后进入FIN_WAIT2状态,然后服务端数据发送完后回送一个FIN报文段进入LAST_ACK状态,客户端收到后发送一个ACK报文段然后进入TIME_WAIT状态,等待一定时长后关闭连接,服务端则在收到ACK报文段后断开连接。

状态转移图

图片4.png

TCP握手为什么两次不可以

  两次握手意味着服务端收到SYN报文段后即认为连接已经建立,并为其维护相关系统资源。但客户端在发送SYN报文段后可能由于网络原因服务端的SYN,ACK报文段并没有送达客户端,此时客户端不认为连接已经建立也不会发送数据,服务端则将维护相关系统资源一段比较长的时间,造成浪费。

TCP握手为什么不用四次

  TCP是全双工通信,原本的握手模型确实应该像挥手一样进行四次的,但是服务端回复ACK和发送SYN之间并没有联系,所以可以合并为一次发送,故TCP握手只需要三次。

TCP三次握手初始序列号为什么不用固定值

  防止串话,防止上一个连接的分组在本次连接建立后才传来并且在同一个窗口中。

TCP的Keepalive

  服务端每过一段时间(两小时)会发送一个心跳包(ACK报文段,序号为当前序号-1); 正常情况下客户端回送一个ACK报文段;
客户端异常掉线(断电之类的),则服务端每过一定时间(默认1000ms)发送一次心跳包,重复一定次数后关闭连接;
  客户端断电之后OS又重启了,则OS会帮助回送一个RST报文段。

SYN洪泛攻击

  攻击者发送大量的SYN报文段,而不完成第三次握手的步骤。随着这种SYN报文段纷至沓来,服务器不断为这些半开连接分配资源,导致服务器的连接资源被消耗殆尽。现在有一种有效的防御系统,称为SYN cookie。
  当服务器收到一个SYN报文段时,服务器不会为该报文段生成一个半开连接。相反,服务器生成一个初始TCP序列号,该序列号是SYN报文段的源和目的IP地址与端口号通过仅有服务器知道的哈希函数算得。重要的是,服务器并不记忆该cookie或任何对应与SYN的其它状态信息。(之前三次握手讲的方法分配了缓存和变量,即记录了状态信息)
  如果客户是合法的,那么它将返回一个ACK报文段,当服务器收到ACK,需要验证该ACK是否与前面发送的某些SYN相对应(之前三次握手讲的方法分配了缓存和变量所以不需要验证)。做法是将SYNACK报文段中的源和目的地IP地址与端口号执行同样的哈希函数,如果结果+1与SYNACK报文段中的确认号相同的话,则认为该ACK对应于较早的SYN报文段,因此它是合法的,生成一个具有套接字的全开的连接。

TIME_WAIT作用

  确保最后一个ACK报文段成功发给服务端。
  确保网络中迷途的报文段消逝,防止串话。因为有的网路可能出现问题,导致之前的一些分组没有成功送达,然后触发超时重传。而后当前连接断开后又重新建立了一个新连接,此时之前的分组可能会发送过来,造成串话。等待一个2MSL时间,是因为IP数据报中有一个生存时间,当数据报在网络中传输了一定跳数还没到达目的地的话就会丢弃该数据报,等待2MSL时间可以确保分组已经被网络丢弃。

Linux中如何查看TIME_WAIT状态,如何解决TIME_WAIT过多

  用netstat命令查看。
  过多可以修改sysctl.conf配置文件:
net.ipv4.tcp_tw_reuse = 1,TIME_WAIT状态套接字可立即用于建立新连接;
net.ipv4.tcp_tw_recycle = 1,操作系统加快TIME_WAIT状态套接字的回收;
net.ipv4.tcp_fin_timeout = 30,设置time_wait等待时间。

TIME_WAIT为什么是2MSL

  保证客户端的ACK报文段在1个MSL中消逝后,服务端超时重传的FIN报文段在1个MSL内发送过来能被客户端接收到。

出现大量CLOSE_WAIT状态的原因及解决方法

  CLOSE_WAIT状态出现于收到FIN报文段但一直没有回送FIN报文段的时候,一般是因为服务端处于忙读等状态,所以要处理好断开连接的情况,在read返回值为0或read返回值小于零查errno不是EAGAIN就断开连接。

IP和MAC地址作用

  MAC是硬件的地址,由链路层负责。IP是网络层IP协议提供的地址格式,是网络中每一个节点的逻辑地址,用以屏蔽硬件地址的差异。

请你说说IP层怎么知道报文该给哪个应用程序,它怎么区分UDP报文还是TCP报文

  多路分解:IP数据报头部记录了协议标识,传输层报文头部记录了目的端口号。

7层模型和4层模型,每层列举2个以上协议

应用层(报文) 应用层 HTTP,SMTP,DNS,FTP
表示层
会话层
传输层(报文段) 传输层 TCP,UDP
网络层(数据报) 网络层 IP,ICMP,ARP
数据链路层(数据帧) 网络接口层
物理层

搜索baidu用到了哪些协议

应用层:DNS,HTTP,SSL
传输层:TCP,UDP(DNS用了UDP)
网络层:IP,ARP

DNS解析流程

1、DNS客户端从url中抽取域名,与根服务器之一联系
2、根服务器返回顶级域服务器地址,与顶级域服务器联系
3、顶级域服务器返回权威服务器地址,与权威服务器联系
4、权威服务器返回域名地址

DNS端口号

53

交换机和路由器区别

  交换机工作在数据链路层,能识别MAC地址,根据MAC地址转发数据帧。
  路由器工作在网络层,能识别IP地址,维护路由表,选择最佳转发路径。

路由选择算法

Dijkstra;
距离向量算法:不时地像相邻节点发送自己的距离向量副本,收到副本的节点使用Bellman-Ford方程更新自己的距离向量副本。

端口号最多多少,为什么?

65535,因为运输层报文段头部存放端口号的字段占16位。

close是一次就能直接关闭的吗,半关闭状态是怎么产生的

  不是,只是将引用计数-1。半关闭状态是LAST_ACK状态,给对端发送FIN报文段后等待ACK报文段。

MTU和MSS

  MTU:Max Transmit Unit,是数据链路层的特性,限制了网络层每次最大的传输数据大小。
  MSS:Max Segment Size,是传输层对应用层每次最大传输数据大小的限制,不包含TCP和IP头部,若MTU为1500,则MSS为1500-20-20=1460.

网络层分片的原因和实现

  数据链路层有MTU的限制,若IP数据报比MTU要大,则需要分片传输。
  实现上,有一个标识位,表示原始报文段的序号;有一个标志为,表示当前分片是否为最后一个分片;有一个分片偏移,表示当前分片在原始报文段的位置。

3、HTTP

说说http协议

  http协议是一种基于TCP的,无状态的应用层传输协议。它基于B-S和C-S架构,定义了一种文件传输格式:请求报文包含请求行,请求头,和请求包体;响应报文包含状态行,响应头,和响应包体。

HTTP和HTTPS区别

  HTTPS并不是新的协议,而是http先与SSL通信,然后再和TCP通信。
  使用HTTP的话,因为是明文传输,所以内容可能被窃听;也无法保证内容完整性,即无法保证内容没有被第三方篡改;没有验证对方身份,因而可能遭遇伪装。

HTTP1.0和HTTP1.1

http1.1:
默认长连接;
增加管线化,可以同时发出多个请求,无需一个个等待响应;
完善cache机制,过期的页面不会删除,而是改为stale对象,与服务器重新激活;
增加断点续传;
增加错误码;

HTTP返回码

1xx:信息性状态码 100:continue
2xx:成功状态码 200:OK
3xx:重定向状态码
4xx:客户端错误状态码 404:页面不存在
5xx:服务端错误状态码 503:服务不可用

https的网站用http打开会怎么样

  一般的网站会返回301重定向响应报文

HTTPS原理

1、浏览器向服务器443端口发送请求,并携带浏览器支持的哈希算法和加密算法。
2、服务器选择一种哈希算法和加密算法,然后将数字证书发给浏览器。
3、浏览器从内置的可靠机构列表中找到相应机构的公钥,解密数字证书,获得服务器公钥,然后生成随机数,使用服务器公钥加密发给服务器。
4、服务器使用私钥解密后使用随机数生成公钥,然后之后使用对称加密与浏览器进行通信。

GET和POST区别

1、语义上,GET用于获取服务器资源,POST用于向服务器修改或提交数据,比如restful风格中就规范了POST的使用,只用于新建而GET用于查询数据,不改变数据的状态。
2、限制上,浏览器一般会限制GET方法的url长度,而POST方法的url在请求包体中。
3、速度上,GET方法更快,因为GET方法和POST方法请求流程不同,GET方法是将头和包体一次发给服务端,然后服务端回复一个200 OK;而POST方法是先发送头部,服务端回复一个100 continue,然后浏览器再继续发送包体,最后服务端回复一个200 OK。另外,GET方法会被浏览器缓存,进一步提高了速度。

RESTful

  Restful是一套web api设计风格,不是标准,它的核心是面向资源而不是面向操作,所以restful api的设计风格是使用URL定位资源,使用HTTP动词(GET,PUT,POST,DELETE等)描述操作。
  如果以操作为中心,容易设计出需要前置操作的操作,这种操作多了系统就乱了,而以资源为中心的话就很容易切断这些关联,并且以资源为中心也更容易设计缓存系统和规范一致的URL。

coockie被禁用怎么实现http的状态化

对于会话coockie来说:
URL重写,在后面加上sessionID;
个人认为长连接也可以。

session和coockie区别

  session数据放在服务器上,coockie数据放在客户端上,都是保存http状态的手段。

讲讲xss

  过分信任服务器发来的代码,让服务器代码随意在浏览器上执行.
  反射型:伪造出恶意URL,服务器根据该URL修改页面的某些内容并发过来,而这部分内容会造成攻击.
  存储型:向服务器提交有恶意代码的内容(如论坛内容),之后的人访问就会被攻击.