TCP怎么保证稳定性
- 序列号/应答/超时重传机制:接收方在就收到消息后,需要发送一个应答信号,其中确认序号表示期望下一帧接受的数据的序号。如果发送发超过一定的时间没有收到应答信号,会重新传输,这个时间为 一个包往返时间 x 2 + 固定偏移时间。
- 滑动窗口:如果每收到一个包都需要应答的话,发送速度就很慢。因此TCP中使用滑动窗口来表明接收端一次最大可接受的数据的长度。发送方不需要等待接受方的应答信号,可以一次发送多个包出去,接受方也不用每个包都应答,只需要对接收到的最后一包序号做应答即可,如果发送发接收到了相同的应答信号超过三次,重发该序号以后的包。
- 拥塞控制:按照上述方法,如果把窗口设置的很大,发送方连续发送太多的包,就会导致网络拥堵,因此使用 慢开始 快恢复 的策略解决。通过一个拥塞窗口变量控制。起始拥塞窗口大小为1,发送方只发送一个包,收到应答后,一次发送两个包,依次,4,8,12….当拥塞窗口大小大于阈值时,进入拥塞避免阶段,将拥塞窗口的增长方式更换为线性增长,即每次加1。期间如果出现了超时,那么发送方将阈值设置为当前窗口的一半,拥塞窗口设置为1,重新开始慢启动的过程。如果出现了拥塞,即发送方收到了三次相同的应答信号,代表 了一部分包,只将拥塞窗口减半,并采用线性速度增长,这就是快恢复过程。这样可以达到:在TCP通信时,网络吞吐量呈现逐渐的上升,并且随着拥堵来降低吞吐量,再进入慢慢上升的过程,网络不会轻易的发生瘫痪。
TCP三次握手四次挥手
三次握手:服务端处于监听状态,等待客户端的连接请求。
- 客户机发送请求报文 SYN= 1, ACK = 0 信号,并设置一个随机的初始序号x
- 服务器收到请求连接的报文后,如果同意连接,发送应答报文, SYN= 1,ACK =1 确认序号为x+1,初始序号值设置随机y
- 客户机收到服务器的应答信号后,确认收到的应答序号是否为 x+1,并再次应答,应答的确认序号为 y+1,序号为 x+1
源 IP 可以伪造,所以要随机。报文不一定会按发送的时序到达目标,所以要加一。
三次握手的原因:首先前两次发送和应答是必要的,相当于请求连接方需要确认对方存在,所以需要确保能收到对方的应答。而第三次应答也是必要的,这是为了防止服务端打开重复的连接。当初始客户端发送的连接请求超时后,客户端会重新发送新的连接请求。但是超时的请求最终会到达服务端,通过第三次握手,客户端可以过滤调延时到达的连接请求。至于四次就不需要了,因为三次已经很稳定了。
四次挥手:由于TCP是全双工的协议,因此在一方请求释放后还需要等待另一方也同意释放,才算完全释放(确认号都为收到的序号+1,ACK值在连接建立后都为1)
- 客户机发送 FIN=1 sew = x 的释放报文
- 服务端收到释放报文后发送一个 响应报文,确认序号为 x+1 此时服务端可以接着将剩余数据发送完,服务端进入close wait状态
- 当服务端准备释放后,向客户机发送FIN=1的释放报文,序号为 y 确认序号为 x+1
- 客户机收到服务端的释放报文后,向服务端发送确认报文,序号为x+1,确认序号为y+1,并等待两个 时间周期(报文最大生存周期) 即可关闭。
四次挥手的原因:当一方想要请求释方连接时,需要主动发出释放请求,同时还需要知道对方同意释放了,因此前两次是必要的。但是由于是全双工通信,此时服务端可能还有数据每发完,因此当服务端发完剩余数据后还需要再发送一个释放连接请求,然后应答。延时等待是 因为 因为防止服务端未收到客户端发送的应答信号,服务端会再次重发FIN,此时客户端认为服务端错发了数据,就会回应RST信号,这时服务端也会认为出错。同时也为了让本连接时间段内产生的报文从网络中消息。
TIME WAIT 是主动关闭端在最后一次应答后需要等待的时间 发生在主动释放端
CLOSE WAT 是被动关闭端在收到请求释放信号后的状态,这个时间用将自己剩余的数据发送完
TCP的模型,状态转移
OSI七层模型和TCP/IP四层模型,每层列举2个协议
物理层:用于定义如何在不同传输媒体上传输bit流,向数据链路层屏蔽不同的传输介质的差异。传输的是比特流。协议有 802.11,RJ45等
数据链路层:用于点的点的数据帧的传输。由于物理层传输的bit可能有误差,因此数据链路层将物理层的bit流封装成帧同时采用一定的差错检验重传的机制来为网络层提供高质量的数据帧传输服务。PPP MAC协议
网络层:用于数据包的源到宿的传递和网际互连服务,通信单位是主机。传输的是数据包。IP ARP ICMP协议
传输层:用于端到端(进程)的可靠报文传递和恢复,传输的单位为报文,TCP UDP
会话层:建立、管理和终止会话,传输单位为SPDU,主要包括的协议为RPC NFS
表示层: 对数据进行翻译、加密和压缩,传输单位为PPDU,主要包括的协议为JPEG ASII
应用层: 允许访问OSI环境的手段,传输单位为APDU,主要包括的协议为FTP HTTP DNS 应用层 :为特定应用程序提供数据传输服务,例如 HTTP、DNS 等协议。数据单位为报文。
搜索baidu,会用到计算机网络中的什么层?每层是干什么的
首先如果是新接入网络的主机需要通过DHCP协议向DHCP服务器获取自身的ip。
- 首先将一个DHCP请求报文传递给传输层,传输层将目的端口和源端口设置为 67 68 后组成一个UDP报文
- 将UDP报文向下传递给网络层,由于此时还没有ip地址,因此将目的ip和源ip分别设置为 255 0 组成一个ip数据包
- 将ip数据包向下传递给数据链路层,由于此时主机并不知道DHPC服务器的MAC地址,因此将源和目的MAC都设置为255 以广播的形式将请求以广播的形式发出
- 当DHCP服务器接收到广播信息后 向上层层处理 得到IP,UDP报文后得知这是一个DHPC请求,需要对他做出响应,将分配的IP地址,子网掩码,DNS服务器的IP地址,默认网关路由器的IP地址和子网掩码 等信息放进一个DHCP响应报文中发出。
- 主机收到 该帧后就可以设置自身的IP地址等信息
在知道了自身的IP地址以及网关路由器的IP地址后,便可以对输入的域名进行解析了。首先会在本地缓存中查找,如果没有就要通过DNS协议像DNS服务器获取域名到IP地址的转换。主机在向网关路由器发包时还需要通过 ARP协议去查询网关路由器的 MAC地址,如果本地已经有了ARP缓存可以直接读出来。完成上述步骤之后,便可以通过DNS协议向DNS服务器查询域名对应的IP地址了。获取IP地址后,主机通过应用层的http协议向服务端请求页面,如果使用的是https协议,还需要加密。http使用TCP协议来传输,TCP协议是传输层的一个协议,http报文传递给传输层后 TCP 可能会对报文分片并加上TCP协议相关的信息后传递给网络层,网路层使用IP协议实现数据包的网际路由功能,根据一定的路由选择算法例如内网的 Ford 和 OSPF算法,外网的BGP路由算法来实现网际数据的发送,当然在内网传递的数据报还需要通过ARP协议来获取网关路由器的MAC地址,并使用MAC协议在数据链路层转发到网关路由器。
HTTP 和 HTTPS 的区别
- HTTP 使用明文通信,不对通信内容加密,存在被侦听的风险,不安全。而HTTPS 使用TLS协议对内容进行加密,更安全
- HTTP 会话建立的过程只需要TCP的三次握手,而HTTPS建立延迟较高,因为需要TLS握手协商对称加密的密钥
- HTTPS 要求服务端向认证机构申请获取证书,同时需要客户端安装对应的根证书
- HTTP端口80 HTTPS 端口443
HTTPS 缺点:
- 握手的时候还要 协商 对称密钥 所以HTTPS协议握手阶段延迟增加
- 需要认证证书和根证书,所以麻烦,并且加密解密需要cpu资源
HTTPS 的加密原理是 首先通过 客户端向服务端获取公钥,即证书,这个证书需要服务端向特定机构认证。客户端在获取服务端发来的证书后需要对证书认证,而这个证书实际就是一个公钥,客户端使用公钥对生成的 随机数进行 加密,发给客户端,客户端使用私钥解密获得这个随机数,这个随机数即为随后对话过程中对称加密用的私钥。这样做是因为公钥加密比较耗时,对称加密速度快。
http+ssl实现https / https如何加密
- 客户端向服务器端发起SSL连接请求;(在此过程中依然存在数据被中间方盗取的可能,下面将会说明如何保证此过程的安全)
- 服务器把公钥(证书)发送给客户端,并且服务器端保存着唯一的私钥;
- 客户端用公钥对双方通信的对称秘钥(类似客户端生成的随机数)进行加密,并发送给服务器端;
- 服务器利用自己唯一的私钥对客户端发来的对称秘钥进行解密,在此过程中,中间方无法对其解密(即使是客户端也无法解密,因为只有服务器端拥有唯一的私钥),这样保证了对称秘钥在收发过程中的安全,此时,服务器端和客户端拥有了一套完全相同的对称秘钥。
- 进行数据传输,服务器和客户端双方用公有的相同的对称秘钥对数据进行加密解密,可以保证在数据收发过程中的安全,即是第三方获得数据包,也无法对其进行加密,解密和篡改
认证 签名
HTTP 返回码
- 1xx 请求已成功接收,需要进一步处理
- 2xx 请求已经成功、接受、理解
- 200 :ok 客户端请求成功
- 206:服务器已经正确处理部分GET 请求,实现断点续传或同时分片下载,该请求必须包含Range 请求头来指示客户端期望得到的范围
- 3xx 要完成请求需要进一步操作
- 300: 可选重定向请求,被请求的资源有一系列可供选择的反馈信息,由浏览器/用户自行选择其中一个
- 301: 该资源已被永久移动到新位置,将来任何对该资源的访问都要使用本响应返回的若干个URI之一
- 302: 请求的资源现在临时从不同的URI中获得
- 304: 请求报文头部包含条件,但是无法满足条件服务器就会返回304
- 4xx 客户端请求报文格式错误或者无法完成请求
- 403: 服务器收到请求,但是拒绝提供服务
- 404:请求资源不存在,无法找到文件。举个例子:输入了错误的URL
- 5xx 服务器无法完成合理的请求
- 500:服务器正在执行请求时发生错误
- 503:服务器暂时处于超负载或正在进行停机维护,现在无法处理请求
http1.0 1.1 2.0改进
HTTP 1.0:(默认短链接)HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接。
HTTP 1.1:默认 长连接流水线模式 ,需要自己断开。客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果。防止客户端无法解析。
HTTP2 对底层传输改动比较大:
- HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络的流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。头压缩能够很好的解决该问题 。(以前key-value 的消息头,使用静态表和动态表压缩,动态表会变化,使用哈夫曼编码吧 )
- 多路复用,HTTP1.1中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制。超过限制数目的请求会被阻塞。而 HTTP/2 做到了真正的多重请求-响应。HTTP/2 把 HTTP 协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息,并行地在同一个 TCP 连接上双向交换消息;同时,流还支持优先级和流量控制。
- 服务端推送 :服务端推送是一种在客户端请求之前发送数据的机制。例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。当客户端需要的时候,它已经在客户端了。(如果一个请求是由你的主页发起的,服务器很可能会响应主页内容、logo 以及样式表,因为它知道客户端会用到这些东西。这相当于在一个 HTML 文档内集合了所有的资源)
为什么Http2可以多路复用?
因为Http传输的文本格式限制了并发的解析,不读到分隔符/换行符就不知道什么时候能把该请求读完,所以也不知道该从哪里读下一条请求,而二进制格式传输数据的方式,采用帧结构,每一帧前都有帧头表示该帧的长度。这样就可以快速分配内存,执行下一次读取。
IP地址作用,以及MAC地址作用
MAC地址是设备的硬件地址,每个网络设备都有唯一的MAC号,用于数据链路层对同一个局域网的网络设备寻址。而IP地址是IP协议提供的,为互联网中每个设备/主机分配的唯一逻辑地址,以此来屏蔽物理地址的差异。
请介绍一下操作系统中的中断
中断是指程序执行过程中,遇到急需处理的事件时,CPU暂停当前正在执行的任务转,保存现场,然后去处理对应的中断事件,处理完后再返回中断处继续执行之前的任务。 中断分为两步:中断响应 和 中断处理,前者由硬件完成后者程序完成。产生中断的原因有三种。
- CPU外部事件,例如IO中断,定时器中断等
- 程序处理异常,例如栈溢出,浮点溢出,指针越界等
- 程序使用了系统调用引起
TCP/UDP的异同
- TCP 是面向连接的,而UDP是无连接的
- TCP 是点对点传输,而UDP可以一对多多对一,多对多等
- TCP 是可靠传输,保证传输数据包无差错,不丢失,按序到达;而UDP是尽可能交付
- TCP 传输的是字节流 具有拥塞控制 和 流量控制,会根据接受方的接受缓冲或者网络状况设置数据包的长度和发送发速度。而UDP面向报文传输,不合并不拆分,保留上面传下来的报文边界。
- TCP 首部开销大,20字节,UDP 开销少8字节。源端口 目的端口 数据长度,校验和
- TCP 效率低但是可靠性好 UDP 反之。所以二者应用场景不同,TCP通常用在文本传输等需要保证正确性的场合,而UDP用在例如视频传输这种实时性要求高但是对错误有一定容忍的场合。
各自应用场景: 对于效率较高,但是准确性要求相对高的场景。例如文件传输,接受邮件,远程登录等;对于实时性的场景,但是对准确性要求没那么高的场景例如 QQ聊天,在线视频(多人同时视频)偶尔断续不是太大问题,并且此处完全不可以使用重发机制。
TCP粘包的原因和解决方法
发送端:如果接受取的缓冲区比较大,TCP发送端为了减少发送数据包的数量,将发送间隔较短的数据包合成一个大的数据包一起发送。而TCP传送的是字节流,没有消息边界,像流水一样,因此这样接收端收到后无法较好的将数据包拆分。
接收端:如果接收端没有及时将接收缓冲区的数据取出,也会导致粘包
解决办法:从协议上入,发送端强制发送,接收端强制接收(破环了协议的封装性);从应用程序上:双方约定一些协议,(包定长、包尾、加入包头信息)
UDP如何传输文本文件
在应用层上加入tcp的可靠性传输,加包号,接收方对包号进行检查,滑动窗口机制(发送文件的数据量)和拥塞机制(发送方速度)
UDP为什么有边界
udp基于数据报,一个数据报必须作为一条单独的消息发送,即使接收端连续收到两条消息,应用程序也必须要通过两次读取才行,所以就有了边界。
请你说一说HTTP协议
HTTP是超文本传输协议的简称。定义了客户机如何从服务器获取web页面的请求协议,以及web服务器如何把web页面传送给客户机。HTTP采用了请求响应模型,客户机发送一个请求报文,请求报文内容 为:首先第一行为请求类型,有get head post , URL 和 协议版本,接着是请求头部信息,key-value形式组成,然后空行接请求主题。响应报文的内容为:协议版本 和 应答状态号及对应的描述,接着是响应头部信息,空行和响应主体信息。
HTTP有如下特点:
- 简单快速:从上述描述可以看出报文结构简单。由于HTTP协议简单,使得HTTP 服务器的程序规模小,因而通信速度很快。
- 无连接:是指每次请求响应完毕后就关闭连接,这样可以避免一个客户机一直占用端口
- 灵活:可以传输任意类型的数据,使用 cotent-type来描述
- 无状态:无状态是指HTTP协议对于事务处理没有记忆能力。缺少状 态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接 传送的数据量增大,优点是,在服务器不需要先前信息时它的应答就较快
- 使用80端口,TCP/IP协议传输
- 支持C/S B/S模式
一个使用HTTP的例子如下:
- 在浏览器输入URL,本地浏览器首先使用DNS协议向根域名服务器获取域名对应的IP地址(也有可能本地有缓存就不需要像服务器获取)
- 获取到服务器IP地址后,根据IP地址和80端口,和服务器建立TCP连接
- 浏览器发送读取文件的HTTP请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器
- 服务端获取到请求报文后,将对应的HTML文本发送给浏览器
- 若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接; 若connection 模式为keepalive,则 该连接会保持一段时间,在该时间内可以继续接收请求;
- 浏览器解析响应报文 显示收到的html内容
GET 和 POST的区别
本质上说,GET 适用于从服务端读取数据,而POST用于更新服务端的数据。GET只需要发送一次请求报文,服务端响应200 ok即可。而POST 则先发送 header,响应 100 continue 后 再发送主要数据,接受200 ok即可。
总的来说二者有如下区别:
- GET 通过URL 提交数据,把数据放在 url 后,而 POST 放在 HTTP 包体中
- GET 使用 URL 所以支持的参数长度有限,且只支持 ascii 编码,而POST没有这个限制
- GET 的参数直接暴露在 url 中所以不能用来传递敏感参数,没有POST安全
- GET 浏览器会主动缓存get的参数,而Post不会
- GET 和 POST 本身并无差别,都是TCP连接, 但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
socket编程中服务器端和客户端主要用到哪些函数
(请问你有没有基于做过socket的开发?具体网络层的操作该怎么做)
- TCP 服务端
- 打开 一个 socket
- bind 绑定ip地址和端口号到 socket 上
- 使用 listen 监听端口
- 收到连接请求后 使用 accept 函数建立连接
- 调用 read / write 读取发送数据
- TCP 客户端
- 打开一个 socket
- 设置要访问的服务器 端口号 和 ip
- connect 和主机建立连接
- read / write 读取发送数据
- close 关闭连接
- UDP 服务端:
- 打开 一个 socket
- 使用 bilind 绑定要监听的端口
- 使用 recvfrom 接收客户端的消息
- sendto 发送数据
- 关闭 close
- UDP 客户端
- 打开一个socket
- 设置服务器的地址 ip 和 端口
- 使用sendto 和 recvfrom 向主机发送和接受数据
- 关闭 close
(socket 的 type 参数 SOCK_STREAM SOCK_DGRAM 表示使用的TCP/UDP协议)
select,epoll的区别,原理,性能,限制
和阻塞式I/O模型一样都会阻塞当前线程,但是多路复用的优点是 可以一次性监视所有socket的变化,通过将文件描述符集合传递到内核,让内核监视所有socket的状态,一旦其中有一个数据准备好就会返回,效率相对 阻塞I/O更高。缺点是 需要进行两次系统调用,一次是 select 一次是 recvfrom。因此当连接数不是很高的话,多线程+阻塞式I/O模型效率反而更高。
- select : 每次在使用 select 之前要将文件描述符集合 从用户空间拷贝到内核空间,并遍历一遍(在内核空间遍历)如果有就绪的文件,则直接返回;如果没有,根据select设置的超时参数来决定等待多久再返回(如果超时参数为null,为阻塞式,只有当某个文件就绪后才会唤醒该进程,否则就根据超时时间主动返回select),将fd从内核态拷贝到用户空间,然后在应用层轮询遍历找到响应的连接。
- 由于文件描述符集合使用数组实现,因此可处理的最大连接数不是很多(多了也不行因为轮询遍历就会很慢)
- 需要轮询判断具体哪个文件描述准备就绪,因此连接数多了之后 复杂度多
- poll:相对 select 么有太大的区别,只是将数组换成了链式结构,从而支持同时处理更多的连接了
- epoll:解决了上述需要轮询的问题,通过注册回调函数实现,需要监听的文件描述符用一个红黑树维护,当某个事件发生时通过注册的回调函数将响应的文件描述符添加到链表中。因此 不再需要程序轮询遍历。
- LT:LT模式是指水平触发,支持阻塞和非阻塞模式,内核会告诉你一个文件描述符是否就绪,如果你不进行任何操作,还是会继续通知你。对读比较友好,得到通知后读一次就行不一定非要一次读完所有的数据因为下次还会再同时,但是对写不友好,因为发送缓冲区大部分都是空的,如果你并不想发数据,并且socket一直在监控中他就会一直通知写事件,所以必须保证没有数据要发送的时候把他从监控列表中移除
- ET:边缘触发模式,只支持非阻塞,内核在通知你一个文件描述符就绪后,如果你不进行处理,以后不会再通知。这个对读不友好,必须非阻塞的一下读完所有的数据,否则如果没有新增的数据到来,那么之前残留的没读完的数据他也不会再通知了,但是如果一次读的数据过长会带来饥饿问题。
- 两个模式的优缺点是:ET模式效率更高,减少了epoll 重复触发的次数,但是ET模式下必须使用非阻塞模式的套接口,避免由于一个文件的阻塞读写操作而忽略了其他的响应,因此这种可能会漏处理,需要更严谨的程序逻辑。
select 应用场景 select 的 timeout 参数精度为微秒,而 poll 和 epoll 为毫秒,因此 select 更加适用于实时性要求比较高的场景,比如核反应堆的控制。select 可移植性更好,几乎被所有主流平台所支持 poll 应用场景 poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select epoll 应用场景 只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接。需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且 epoll 的描述符存储在内核,不容易调试。
其实 select 不好是因为 内核 是没有记忆的,因此每次都要将 文件 描述符从用户空间向内核空间拷贝,实际中首先管理的文件描述符变动不大,因此没都全盘拷贝做了很多无用功。为了使得内核对我们需要管理的文件描述符有记忆,在内核中新建了一个 eventepoll 文件对象,它是存在内核中的,并且其中维护一个红黑树用于存储所有的文件描述符,用户通过 epoll_ctr 来向它注册要管理的文件描述符。同时还维护一个就绪队列,当某个文件就绪就将它添加到就绪队列中,通过回调函数实现。而用户只用调用 epoll_wait 去访问就绪队列是否为空即可。所以它不用遍历所有管理的文件描述符,也不用每次都要将所有的文件描述符从用户空间拷贝到内核空间。参考连接
epoll wait 流程:
- 服务器创建非阻塞 socket(server_fd)。
- epoll_create 创建 epoll 事件驱动 (epoll_fd)。
- epoll_ctl 监控 server_fd 的可读事件 EPOLLIN。
- 服务进程通过 epoll_wait 获取内核就绪事件处理。
- 如果就绪事件是新连接,accept 为客户端新连接分配新的文件描述符 client_fd,设置非阻塞,然后 epoll_ctl 监控 client_fd 的可读事件 EPOLLIN。
- 如果就绪事件不是新连接,read 读取客户端发送数据进行逻辑处理。
- 处理逻辑过程中需要 write 回复客户端,write 内容很大,超出了内核缓冲区,没能实时发送完成所有数据,需要下次继续发送;那么 epoll_ctl 监控 client_fd 的 EPOLLOUT 可写事件,下次触发事件进行发送。下次触发可写事件发送完毕后, epoll_ctl 删除 EPOLLOUT 事件。
- 客户端关闭链接,服务端监控客户端 fd,如果 read == 0,close 关闭对应 fd 从而完成四次挥手
为什么ET一定要非阻塞
阻塞:请求获取资源后,如果没有没有获取到则一直等待 非阻塞:没有获取到则返回为空 如果是 水平触发模式 每次 epoll_wait 后的文件描述符里一定是有东西可以读/写的,因此使用 阻塞的I/O 调用一次 read write 一定不会导致该文件描述符阻塞,而且只读一次都没事,因为是水平触发,你可以只调用一次读,如果此时没读完,下次epoll_wait 他还会再触发,还可以接着读;当然水平触发模式下也可以用非阻塞的方法式,就是 while 循环一直读,直到没有数据返回 erro_block 后退出循环。
但是在边缘触发模式下,只有数据缓冲空到满时会触发一次通知,最后一帧如果没有新增数据那么就不会再通知,所以读的时候必须一下子读完所有的数据 即 while 循环读取所有的数据。但是此时如果你再使用阻塞的IO读,那么最后一帧数据读完后必定阻塞,因为阻塞IO就是如果没数据了就会阻塞读,所以边缘触发模式只能采用非阻塞IO读,最后没有数据了返回ERRO退出while循环
ET模式读的饥饿问题
解决方法:创建一个描述符队列,通知要读的但还未读的就放入该队列中,定时定量去读,读完则将该描述符移除。
使用Linux epoll模型的LT水平触发模式,当socket可写时,会不停的触发socket可写的事件,如何处理?
当需要写出数据时,把数据write到fd中;如果数据较大,无法一次性写出,那么在epoll中监听EPOLLOUT事件 当EPOLLOUT事件到达时,继续把数据write到fd中;如果数据写出完毕,那么在epoll中关闭EPOLLOUT事件
多线程同时操作一个socket问题
设置EPOLL ONESHOT标志位,保证一个socket连接在任一时刻只被一个线程处理
TCP 快速重传为什么是三次冗余 ACK,这个三次是怎么定下来的?
统计概率问题:只收到两次,一定是乱序;乱序也会造成收到三次ack,只不过概率小,如果丢包,一定会收到三次。主要的考虑还是要区分包的丢失是由于链路故障还是乱序等其他因素引发。两次duplicated ACK时很可能是乱序造成的!三次duplicated ACK时很可能是丢包造成的!四次duplicated ACK更更更可能是丢包造成的!但是这样的响应策略太慢。丢包肯定会造成三次duplicated ACK! 综上是选择收到三个重复确认时窗口减半效果最好,这是实践经验。
为什么会乱序:负载均衡、路由器流量调整造成的多路径传送
请你来介绍一下udp的connect函数
- 因为UDP可以是一对一,多对一,一对多,或者多对多的通信,所以每次调用sendto()/recvfrom()时都必须指定目标IP和端口号。在未建立UDP套接字的上调用connect
- 变成了一对一的连接,可以和TCP一样使用write() / send() 传递数据,而不需要每次都指定目标IP和端口号,写到已连接UDP套接字上的任何内容都自动发送到由connect指定的协议地址。可以给已连接的UDP套接字调用sendto,但是不能指定目的地址。sendto的第五个参数必须为空指针,第六个参数应该为0。
- 但是它和TCP不同的是它没有三次握手的过程,调用connect只是预先记录了ip地址和端口号;
- 依然是不可靠传输,如果不调用connnet 那么给同一个目标发送消息 是 连接套接字→发送报文→断开套接字→连接套接字→发送报文→断开套接字 →………效率比较低;connnet 后中间就不会再断开套接字了;连接套接字是需要一定开销的,比如需要查找路由表信息。所以,UDP 客户端程序通过 connect 可以获得一定的性能提升
- 在一个已连接UDP套接字上,由内核为输入操作返回的数据报只有那些来自connect指定协议地址的数据报。这样就限制一个已连接UDP套接字能且仅能与一个对端交换数据报
- 还可以通过在已建立连接的UDP套接字上,再次调用connect()。TCP套接字只能调用一次connect()函数。
- 指定新的IP地址和端口号
- 断开连接
- 由已连接UDP套接字引发的异步错误会返回给它们所在的进程,而未连接的UDP套接字不接收任何异步错误。
ARP地址解析协议
每个主机都会在自己的工作区建立ARP缓冲区(ARP列表),表示IP地址和MAC地址间的对应关系。(不是永久的,隔一会儿更新,因为IP与MAC的对应关系会变)ARP广播查询目的主机的MAC地址,目的主机ARP单播响应自己的MAC地址收到广播响应时比对是否和自己的IP地址相同,相同则响应,不同则丢弃不管,如果广播主机一直没有收到响应,表示ARP查询失败。本网段有机器中病毒或发生故障,不断发送查询导致网络拥塞RARP 逆地址解析协议 MAC解IP
DHCP协议
动态主机配置协议。系统连接到网络上,并获取所需要的配置参数手段。通常被应用在大型的局域网络环境中,主要作用是集中的管理、分配IP地址,使网络环境中的主机动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。
网桥的作用
网桥是一个局域网与另一个局域网之间建立连接的桥梁
ICMP网络控制报文
Ping 检查两台主机是否网络联通 向目的主机发送ICMP Echo 请求报文,目的主机收到后回复Echo应答报文,根据时间和成功率计算出主机间的通信时间和丢包率。Traceout 从源主机到目的主机经过的节点路径,发送IP封装的无法交付的UDP用户数据包,并由目的主机发送终点不可达差错报告报文,TTL由1开始发送,每次累加1,直到收到差错报告报文,即可知从源到目的经过多少路由
TTL (time to live) 生存时间
表示数据包在网络中的时间,经过一个路由该数据包TTL就减1,这是因为有些路由会形成环,如果没有TTL,那么数据包就会在网络中打转,拥塞网络
网络层和传输层协议的区别
网络层用于主机之间的逻辑通信,传输层主要用于进程之间的逻辑通信
应用层和传输层的keep alive区别
传输层TCP的 keep alive 用于 探测连接的对端是否存活,如果对端因为网络,死机导致掉线 或者 处于半连接状态 那么都可以通过 保活报文来处理。
HTTP 的keep alive 打开 是指长连接 可以连续发送多个请求 而不用断开连接
请你说一下阻塞,非阻塞,同步,异步
阻塞和非阻塞:调用者在事件没有发生的时候,一直在等待事件发生,不能去处理别的任务这是阻塞。调用者在事件没有发生的时候,可以去处理别的任务这是非阻塞。
同步和异步:调用者必须循环自去查看事件有没有发生,这种情况是同步。调用者不用自己去查看事件有没有发生,而是等待着注册在事件上的回调函数通知自己,这种情况是异步
讲述一下Socket编程的send() recv() accept() socket()函数
- socket 用于创建一个套接字,返回文件描述符。由于一个机器中可能有很多进程都需要使用相同的TCP 或者 UDP 协议发送接收数据,为了区分不同主机中不同进程,将IP 地址 端口号 绑定到 套接字中,就可以唯一区分互联网中两个主机中需要通信的两个进程。
- send:用于向 TCP 连接的另一端发送数据,一般客户机用 send 将请求报文发送给服务器,服务器用 send 做应答。调用 send 的时候将用户空间中将要发送的数据写入发送缓冲区,然后使用协议发送。
- recv:用于从 TCP 连接的另一端接收数据,等待接收缓冲区中数据接收完毕后,recv函数将缓冲区中的数据读给应用层。
- accept:用于接收 TCP 连接,内部会维护一个 半连接队列 和 一个连接完成的队列,如果连接完成队列为空,则阻塞,否则返回队列第一个连接成功的文件描述符。
http协议会话结束标志怎么截出来
看tcp连接是否有断开的四步挥手阶段
TCP/IP数据链路层的交互过程
数据链路层通过 MAC 地址作为通信目标,数据包到达网络层准备往数据链路层的时候,首先查找自己的ARP表,查找局域网中的 ip-mac映射关系,如果找到了,就将目标IP的MAC地址封装到数据链路层的数据包的包头, 如果没找到就使用广播的方式在局域网中查找,对应IP地址的设备在收到广播后会以单拨的形式将自己的mac地址回复给请求的机器
IP层怎么知道报文该给哪个应用程序,它怎么区分UDP报文还是TCP报文
端口号 包头协标识字段
server端监听端口,但还没有客户端连接进来,此时进程处于什么状态
如果是阻塞式的方式,就处于阻塞状态,如果调用 epoll select poll 这样的 I/O 复用模型,因为需要轮询判断有无响应。是运行状态。
TTL是什么
TTL是 Time To Live的缩写,该字段指定IP包被路由器丢弃之前允许通过的最大网段数量
HTTPS一定安全嘛
不是绝对安全的,可以通过中间人攻击。中间人攻击是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。HTTPS 使用了 SSL 加密协议,是一种非常安全的机制,目前并没有方法直接对这个协议进行攻击,一般都是在建立 SSL 连接时,拦截客户端的请求,利用中间人获取到 CA证书、非对称加密的公钥、对称加密的密钥;有了这些条件,就可以对请求和响应进行拦截和篡改。
客户端断电或网络异常怎么处理
TCP keep-alive 借助心跳机制来感知这种状况,一般的做法是,服务端往对端发送一个心跳包并启动一个超时定时器,如果能正确收到对端的回应,说明在线,如果超时,可以进行一系列操作,比如重试、关闭连接等等。
cookies 和 seesion区别
cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上,通常。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。主要功能是:
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)记录用户信息
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)浏览历史信息
Session 代表着服务器和客户端一次会话的过程。Session 对象存储特定用户会话所需的属性及配置信息,存储在服务端
Cookie 和 Session 有什么不同
- 作用范围不同,Cookie 保存在客户端(浏览器),Session 保存在服务器端。
- 存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等。
- 有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
- 隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
- 存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie
cookies 和 seesion 的关联
SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统根据seesion和cookie来验证用户登录状态。
用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建创建对应的 Session ,请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器,浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名。
当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。
cookie 被禁用了怎么用seesion
可以在 URL 中携带 seesion 参数
HTTP接口的幂等性
幂等性是系统服务对外一种承诺,承诺只要调用接口成功,外部多次调用对系统的影响是一致的。比如在 扣款中 用户如果点击了多次支付,应该只扣一次款。
解决幂等问题可以通过多个角度实现,在客户端 只允许按钮可以被按下一次。在服务端可以使用状态机等,还可以使用token机制,客户端请求时 添加 token 参数,重复的请求token相同,服务端就可以区分了。
https://segmentfault.com/a/1190000020172463
三次握手后最后一次 ack 丢包了会怎样
服务端 会根据超时重传机制重新发送 SYN+ACK报文,一定次数后 还没响应就关闭; 客户端在发送第三次响应包后 就进入了 链接状态,他感知不到服务端是否收到最后一次的握手响应,他会向服务端正常发送数据,Server端将以 RST包响应,方能感知到Server的错误。
ICMP网路控制报文
Ping 检查两台主机是否网络联通 向目的主机发送ICMP Echo 请求报文,目的主机收到后回复Echo应答报文,根据时间和成功率计算出主机间的通信时间和丢包率。
Traceout 从源主机到目的主机经过的节点路径,发送IP封装的无法交付的UDP用户数据包,并由目的主机发送终点不可达差错报告报文,TTL由1开始发送,每次累加1,直到收到差错报告报文,即可知从源到目的经过多少路由
TCP xxx 攻击
IPV4 和 6 的区别
DNS解析过程
什么场景下机器产生大量的time_wait,有什么影响
DNS解析过程以及DNS劫持
阻塞socket和非阻塞socket的区别
从局域网访问一个URL的整个过程,
NAT技术,DNS,ARP协议等