问:什么是IP地址
答:IP是网络互联的协议,是TCP/IP 网络层的协议,设计IP的目的是,提高网络的可扩展性,实现大规模的网络互通,Ip地址是网络上对于设备的识别
问:什么是端口?
答:唯一表示一个主机上的某个进程。
问:什么是网络字节序
答:网络传输的数据是一种字节流,在UDP/TCP/IP中,规定第一个接收到的字节放到高地址,也就是大端字节序,但是不同的主机存在不同的存储方式,为了统一,需要将数据进行网络字节序的转变。
问:常见的网络协议有哪些?
答:数据链路层:Wi-Fi 网络协议层:IP协议 传输层:TCP UDP 应用层:HTTP DNS FTP SSH
问OSI 7层模型
- 物理层:利用传送介质,为数据链路层提供物理连接,实现比特流的透明传输
- 数据链路层:物理寻址,同时将比特流转换为逻辑传输路线(arp 协议,rarp协议)
- 网络层:控制子网的运行,逻辑编址,分组传输,路由选择
- 传输层:接收网络层的数据,必要时进行分割,达到端对端的连接,保证数据的可靠性
- 会话层:不同主机上的用户建立会话管理
- 表示层:将不同的数据格式进行转换,解析语法意义,加密解密,压缩解压缩等
- 应用层:为用户提供各种应用协议。
问:TCP/IP 4层模型?
问:什么是tcp协议?
答:tcp 是面向连接的可靠的流式服务
数据链路层:将数据封装成帧,加上报头和报尾,报头包括了目的MAC地址和源MAC地址
网络层:同过MAC地址找到对应的节点,通过arp 从Ip--MAC 或rarp 从MAC--IP 地址转换
TCP 编程流程
server端socket() --- bind() ----listent()----accept()---recv()----send()----close()
client 端 socket()--- connect() ---send()---recv()---close()
tcp 是面向字节流的,tcp有自己的缓冲,当应用程序传输的字节流太长,tcp就可以分短在传输
- 源端口:标示报文 的返回接口 目的端口:指明接收主机的接口
- 序号和确认号:是tcp传输可靠的关键部分,序号是本报文段发送数据组的第一个字节序号,每一个字节一个序号,例如一个报文段的序号为300,数据部分为100字节,则下一个报文段的序号为400,所以序号确定了tcp的有序性,确认号,即ACK 指明下一个期待收到的字节序号,表明该序号之前的数据,已经准确无误地收到,
- 数据偏移/首部长度 tcp 头部长度不确定,若不包含任何子段是20字节,首部长度是指识了数据区在报文中的起始偏移值。
- 控制位:URG ACK PSH RST SYN FIN
- URG : 紧急指针标记 1 有效, 0 无效
- ACK :确认序号标志 1 有效 ,0标示报文中不含字段确认消息,忽略确认号字段
- PSH :push标志 标示接收方收到数据,应该立即交给应用程序,而不是在缓冲区排队
- RST :重置连接标志 用于重置由于主机崩溃或者其他原因造成的错误连接,或者用于拒绝非法连接
- SYN :同步序号,用于建立连接的时候
- FIN: finish标志,标示没有数据发送了,关闭本方数据流
- 滑动窗口:用来告知发送端接收端所能接受的缓冲的大小,用来控制发送端发送的速率,窗口大小是一个16位bit
- 校验和:奇偶校验,对整个tcp 报头和数据进行校验 发送端计算和存储,接收端验证
- 紧急指针:是发送端紧急发送给服务端数据的一种方式
- 选项和填充:最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。
- 数据部分:TCP 连接 可以有数据部分,也可以没有
三次握手的过程
三次握手发生在connect()建立连接的时候
- 建立连接,客户端给服务器发送连接请求,发送SYN==1,序号seq==x, 然后客户端进入SYN_SEND,等待服务器确认
- 服务器收到SYN报文段,需要对SYN报文段进行确认,然后将确认号ACK=x+1 ,然后将ACK,和SYN==1 ,和序号seq==Y 发送给客户端,服务端进入SYN_RECV状态
- 客户端收到服务端发来的SYN+ACK报文,经应到报文ACK==Y+1,向服务端发送ACK 报文,完成3次握手,客户端和服务端都进入ESTABLISHED
问:为什么要三次握手?
答:因为防止已经失效的连接突然传送到服务端,而造成的资源浪费 例如:一个client向server发送了一次请求报文,但是在某个网络节点上滞留了长的时间,导致连接释放的某个时刻到达server端,而server端以为是一次新的请求,如果没有3次握手,此时服务端就和客户端建立建立,而客户端已经放弃了本次连接,也不发送数据,但是服务器一直等待数据,浪费了资源
问:那个阶段最容易受到攻击?
答:第二个阶段,当客户端伪造了大量的ip地址,然后给服务器发送SYN 请求,当服务器接受到SYN请求时,对SYN 进行确认,由于IP无效,服务器 会多次从发ACK 确认,确收不到客户端的第三次确认,导致服务端的未连接队列沾满,浪费了资源,使得正确连接无法继续,直到到达重传次数上限,或者超时时间,才会放弃这个攻击连接
问:解决办法?
- 缩短Timeout的时间,但是有可能因为网络拥塞导致正常连接失败
- 当未完成序列超过一半时,释放系统资源
- 设置SYN cookie 当server端回复SYN+ACK时,不立即分配数据区,而是通过一种算法,求的一个cookie 放大hash表中,将这个cookie值作为序号加密发送,若短时间收到相同SYN报文,则拉黑IP
问:listen(int fd,int baklog)的第二个参数意义?
答:内核会为我们维护两个队列,已完成队列,和未完成队列,SYN队列就是未完成队列,放着没有完成3次握手的连接,而listen()的backlog时表示,已完成队列中等待accept()最大数目,不同系统数目会比backlog多一个。
问:connect()作用?如何防止connect()长时间阻塞?
答:发起连接,建立三次握手,将connect()设置为非阻塞,用select 或者poll 机制来检测
问: send()发送成功是否代表数据已经到了接受方的缓冲区?
答:send()返回为-1 ,表示失败,=0表示成功写入自己的发送缓冲区,不能表示已经到了对面的接受缓冲区 recv()函数 返回值表示已经接受到字节个数,=-1 失败,=0 表示对方关闭了连接
问:什么是TCP粘包?如何解决?
答:产生粘包原因:
- TCP为了更高的提高效率,Nagle算法往往会收集足够的数据才发送 ,
- 接收方不及时接收消息,导致多个数据被一次recv()
- 发送端缓冲区大于网卡MTU时,会进行拆包
解决粘包问题
- 关闭Nagle算法,使用TCP_NODELAY选项修改
- 每条数据增加特定符号开始和结尾,但是要保证数据内容不要包含特定字符
- 每一条数据前4位为该数据的长度,这样可以根据长度读取数据
问:如何查看缓冲区有多少数据未处理
答:netstat -natp
问:流量控制
答:流量控制就是有可能客户端发送消息太快,而客户端来不及接收,可能会造成数据的丢失,滑动窗口机制很容易的解决了对放的发送速率
TCP 为每个链接维护了一个计时器,当一次滑动窗口为rwnd=400 意思是有400字节的缓冲,当发送方收到rwnd==0表示不能再发
问:拥塞控制
双发维护着一个拥塞窗口,拥塞窗口的大小取决于网络的拥塞程度,动态的变换,原则上只要网络不拥塞,就扩大一点,否则拥塞窗口就减少,
1 慢开始:当开始发送数据的时候,由于不清楚网络的负荷情况,采取试探性的增加窗口的数值,防止造成网络拥塞。
初始设置rwnd=1,开始试探的成倍增加数值,即从1 ---2 ----4----8......... 为了防止一直增大,还要增加一个状态变量ssthresh,当rwnd<ssthresh,启动慢启动算法,当rwnd>ssthresh,采取拥塞避免,当rwnd==ssthresh,两种算法都可以
2 拥塞避免
当rwnd 增加的一定标准,不再是成倍增加,而是加1,一旦判断为网络拥塞,无论是慢启动阶段还是拥塞避免阶段,把开始的状态变量ssthresh设置为最初的一半(不能小于2),然后将rwnd=1,从新开始慢启动
快重传和快恢复
快重传算法要求每次接收到数据后立即发出确认,
当收到m1 m2 ,但是m3 丢失,接收端不对发过来的m4 m5 进行处理,而是再发m2 的确认,这样发送端就知道m3丢失了,所以立即重传m3
快恢复
当收到3次重复确认时,将慢开始的状态变量减半,然后将rwnd设置为ssthresh的值,执行拥塞避免算法。
断开连接的四次挥手
任意一方执行close()函数时,开始执行4次挥手
- 主机1 设置seq的值 seq==X,向主机2发送fin报文段 fin==1, 此时主机1 进入FIN_WAIT_1的状态
- 主机2被动收到FIN报文,向主机一发送ACK确认号ACK=X+1 主机一进入FIN_WAIT_2的状态,主机2进入CLOSE_WAIT状态(此时处于半关闭状态)
- 主机2 向主机一发送FIN=1,自己的seq=z, 主机2 进入LAST_ACK 最后确认状态
- 主机1 收到主机2的FIN后, 发送ACK=z+1 ,然后进入TIME_WAIT状态,主机2 收到ACK 后断开连接,主机1 等待两个报文时间,正常关闭。
问:为什么要4次分手?
答:因为TCP 是面向连接的可靠的,字节流式服务,而且是全双工模式,因此每个方向都是单独进行关闭的,当一方发送FIN只是告诉这边没有数据流动了,但是另一方仍然可以发送数据,只要也发送FIN时,双方才停止数据交流
问:TIME_WAIT的作用?
答:如果主机一直接关闭,由于网络原因,主机二并没有收到最好的ACK确认,那么主机二在超时,从新发FIN 报文,而此时主机一已经关闭,找不到连接,因此需要2个报文时间等待。
如果主机一直接关闭,然后又向主机2 发送一次新链接,假如两次端口号相同,网络中有上次遗留的数据,会被认为是新链接的数据,导致数据混杂。
因此 TIME_WAIT保证让TCP报文有足够的时间识别和丢弃