其他分享
首页 > 其他分享> > 20210531-TCP

20210531-TCP

作者:互联网

1.epoll边缘触发 水平触发
水平触发:如果没有把数据一次性读取完,下次调用epoll_wait的时候,它还会通知你上次没有读写完的socket上继续读写,如果一直没有读完,就会一直通知你。如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会被返回,这样会降低处理程序检索自己关心的文件描述符的效率。
边缘出发:文件描述符可读写状态只会通知你一次,如果没有一次性读取完数据,它下次也不会再通知你。这种模式比水平触发效率高。就绪队列里不会有大量你不关心的文件描述符。通常都是使用这种模式,然后用while循环把数据都读走。
select和poll都是水平触发模式,epoll是可选触发模式。

2.TCP加密
TCP主要是通过明文进行数据的传输。要对数据加密的话,需要加入一些加密算法。
主要分为对称加密和不对称加密。
对称加密是只有一个密钥,通信双方使用相同的加解密算法进行加密和解密。密钥怎么给到另一方比较困难。

非对称加密,有两个密钥,一个公钥一把私钥。流程是这样的,客户端发送支持的加密套件到服务器,服务器选择一个自己也支持的加密套件,给客户端发送此加密套件和公钥。客户端通过生成一个随机数,使用此加密算法使用公钥进行加密,服务器那边接收到加密后的数据,使用私钥进行解密,获取得到密钥,然后在后序的通信中使用这个密钥对数据进行加密。

HTTP加密是先用443端口来获取密文。密文沟通完了之后要转回80端口发送数据。
非对称加密缺陷:客户端发送加密套件给服务器后,被黑客劫持,黑客返回一个加密算法给客户端,客户端保存的是黑客给的加密算法和公钥。
这个问题需要用数字签名来解决。数字签名让客户端确认这个加密算法是服务器发的,而不是黑客发的

3.数字签名
数字签名通过使用私钥进行加密,公钥进行解密。RSA签名,只有私钥加密的内容,才可以被公钥进行正确的解密
因为其他人没有对应的私钥,所以没法生成公钥可以解密的密文,所以是不可伪造的。又因为公钥对应的私钥只有一个,所以只要能成功解密,那么发消息的一定是你,不会是其他人,所以是不可抵赖的。在实际应用中,源数据比较大,直接使用RSA算法进行签名速度比较慢,所以一般只对数据摘要进行加密(签名)。具体过程如下:
1)小明对外发布公钥,并声明私钥在自己手上
2)小明对消息M计算摘要(哈希算法),得到摘要D
3)小明使用私钥对D进行签名(加密),得到签名S
4)小明将M和S一起发送出去
5)接受者对M使用和小明相同的算法进行摘要D
6)使用小明的公钥对S进行解密(解签),得到D’
7)如果D和D’相同,那么证明M确实是小明发出的,没有被篡改。

4.CA认证
数字签名存在的问题是,某黑客篡改了公钥,然后用自己的私钥做成数字签名,再发给接收者。使用数字证书解决此问题。
数字证书是CA签发的较为权威与公正的电子文档。证书的内容包括:CA信息,公钥用户信息,公钥,CA的签名和有效期。
过程:由于接收者不确定自己拥有的公钥是否来自与A,所以他要求A去CA做公钥认证,CA使用自己的私钥,对A的公钥和一些相关信息一起加密,生成数字证书并签名。所以如果A再想给B发消息,他只需要在签名的同时,再付上数字证书即可。B收到消息后,用CA的公钥解开数字证书,就可以拿到A真是的公钥了,然后就可以消失是A发来的。

5.TCP网络字节序
TCP网络字节序是大端字节序,即高位字节存放在低位地址中。主机字节序是不确定的,有可能是大端和小端,所以在网络通信时,发送方先要将主机字节序转换为网络字节序,接收方需要从网络字节序转为主机字节序。这么做还有一个优点是,在代码移植的时候,可以避免字节序不统一的问题了。
验证本机字节序,1.创建一个int变量,强转成一个字节,对比即可得出;2.使用hton* 函数,返回结果相同则是大端字节序

6.网络的tcp四次挥手的time_wait状态说一下
客户端首先发送FIN到服务器,进入FIN_WAIT1状态;服务器端收到后,发送一个ACK给客户端,进入CLOSE_WAIT状态,进行收尾工作;客户端收到ACK后,进入FIN_WAIT2状态,服务器处理完收尾工作后,发送FIN到客户端,进入LAST_ACK状态;客户端收到FIN之后,发送一个ACK到服务器,进入TIME_WAIT状态;服务器收到ACK之后,进入CLOSED状态;客户端在经历2倍的最长报文寿命后,进入CLOSED状态。
因为客户端发送ACK之后,这个包可能丢失,服务器那边没有收到这个ACK,会一直不断的发送FIN报文,所以客户端这边不能立即关闭,它要确定服务器那边接收到了这个ACK。如果服务器那边没有收到ACK,重传了FIN报文,客户端要重发ACK并再次等待2倍的最长报文寿命。2倍的最长报文寿命是指一个发送和一个回复所需的最大时间。如果直到2MSL,客户端都没有收到FIN,那么客户端推断ACK已经成功被接收,结束TCP连接。

7.TCP为什么不能两次握手?
无法确定客户端的接收能力。

8.三次握手过程中可以携带数据吗
第三次握手可以,前两次不能。如果前两次携带数据,如果有人想攻击服务器,他只需要在第一次握手的时候在SYN包中放大量的数据,那么服务器就会消耗过多的资源去处理这些数据。增加了服务器被攻击的风险。第三次握手的时候,客户端已经处于ESTABLISH状态了,并且已经确认了服务器的接收和发送的能力,这个时候相对安全,可以携带数据。

9.为什么要等2MSL
2MSL = 去向ACK消息最大存活时间(MSL) + 来向FIN消息的最大存活时间(MSL)。
为何一定要等2MSL?如果不等,释放的端口可能会重连刚断开的服务器端口,这样依然存活在网络里的老的TCP报文可能与新TCP连接报文冲突,造成数据冲突,为避免此种情况,需要耐心等待网络老的TCP连接的活跃报文全部死翘翘,2MSL时间可以满足这个需求(尽管非常保守)

10.半连接队列和SYN Flood攻击
三次握手前,服务器进入LISTEN状态,同时在内部创建两个队列,半连接队列和全连接队列,即SYN队列和ACCEPT队列。
当客户端发送SYN到服务器,服务器收到后回复ACK和SYN,状态从Listen变为SYN_RECV,此时这个连接被推入SYN队列,即半连接队列
当客户端回复ACK,服务器接收后,三次握手完成,这个时候连接等待被具体的应用取走,在被取走前,它会被推入另一个Accept队列。
SYN Flood攻击属于典型的Dos攻击,就是客户端短时间内伪造大量不存在的IP,疯狂向服务器发送SYN包,此时,服务器要处理大量的SYN包并返回ACK,就会有大量连接处于SYN_RECV状态,占满半连接队列,无法处理正常的请求。由于是不存在的IP,服务器长时间收不到客户端的ACK,会导致服务器不断重发数据,直到耗尽服务器资源。
如何处理?
1)增加SYN连接容量
2)减少SYN+ACK重试次数
3)服务器收到SYN后不立即分配连接资源,而是根据SYN计算出一个Cookie,连同2次握手回复给客户端,在客户端回复ACK的时候带上Cookie值,服务器验证Cookie合法后才分配资源。

11.TCP滑动窗口是什么?
TCP通过滑动窗口来进行流量控制,提高效率。
发送方通过接收方的ACK包中窗口大小觉得发送速度。如果发送方收到的ACK包中窗口大小为0,停止发送,定时发送探测包,查看接收方缓存状态。
假设当前滑动窗口大小为3,发送端发送3个包出去,假设为1,2,3,如果此时3个包都ACK了,窗口向后移动,继续发送;如果都没有收到ACK,则重发3个包,窗口不变;如果1号包没有收到ACK,1号包重发,窗口不变;如果1,2号包收到ACK,3号包没有收到ACK,滑动窗口向后移动两位,重发3号包;如果2号包没有收到ACK,其他收到了,滑动窗口向后移动一位,重发2号包。

12.讲讲tcp和udp的区别,和各自的应用场景,应用场景回答了一两种,感觉面试官不是很满意
TCP是面向连接的可靠的协议,UDP是无连接的报文传输协议。
HTTP,FTP,telnet等都是使用TCP的
UDP场景
1.嵌入式设备,需要电池的,因为发一个包出去就休眠了。如果使用TCP的话,要3次握手4次挥手,只有一个包有用,就很浪费资源,,解决耗电节能的问题
2.音视频通话,(直播用TCP比较多,也有自定义的UDP协议),解决延迟问题,减少服务器资源的使用
3.游戏,如魔兽世界等对时延要求较高的游戏用UDP, 解决延迟问题,减少服务器资源的使用
4.quic和rudp和UDT等在UDP上封装的应用层可靠传输协议, 解决延迟问题,减少服务器资源的使用
游戏中,欢乐斗地主用TCP(因为对延迟没有那么重要,对可靠性要求高)

13.tcp可靠保障
连接管理:保证服务器和客户端都接受发送是正常的
效验和:保证发送的数据是没有损坏的
确认应答和序列号:保证数据是被正确有序的
超时重传:保证丢包后数据会重发
流量控制:通过滑动窗口进行流量控制 滑动窗口大小 = min(接收窗口大小,拥塞窗口大小)
拥塞控制:
慢启动:cwnd(拥塞窗口)
初始化 cwnd=1 表明可以传一个MSS(最大报文长度)大小的数据
每当收到一个ACK,cwnd++; 线性上升
每过一个RTT(合理的往返时延),cwnd*=2; 指数上升
设置一个阈值sshthresh,当 cwnd >= sshthresh时,进入拥塞避免算法

拥塞避免:
收到一个ACK,cwnd += 1/cwnd;
收到一个RTT,cwnd += 1;
这样就避免了增长过快导致网络拥塞,慢慢调整到网络的最大值

快重传:分超时重传和快速重传
sshthresh = cwnd / 2
cwnd = 1
进入慢启动状态,TCP认为这种情况太糟糕,反应也很强烈(超时重传)

快速重传在收到3个duplicate ACK时就开启重传, 而不用等到RTO(超时重传机制)超时
cwnd = cwnd / 2
sshthresh = cwnd (快速重传)
进入快速恢复算法

快恢复:快恢复和快重传一般同时使用
快速恢复算法是认为,你还有3个Duplicated Acks说明网络也不那么糟糕,所以没有必要像RTO超时那么强烈,进入快恢复
cwnd = sshthresh + 3 * MSS (3的意思是确认有3个数据包被收到了)
重传Duplicated ACKs指定的数据包
如果再收到 duplicated Acks,那么cwnd = cwnd +1
如果收到了新的Ack,那么,cwnd = sshthresh ,然后就进入了拥塞避免的算法了

如果你仔细思考一下上面的这个算法,你就会知道,上面这个算法也有问题,那就是——它依赖于3个重复的Acks。注意,3个重复的Acks并不代表只丢了一个数据包,很有可能是丢了好多包。但这个算法只会重传一个,而剩下的那些包只能等到RTO超时,于是,进入了恶梦模式——超时一个窗口就减半一下,多个超时会超成TCP的传输速度呈级数下降,而且也不会触发Fast Recovery算法了。

14.TCP Nagle算法(控制TCP报文段的发送时机):
避免发送大量的小包,防止小包泛滥于网络
发送方将第一个数据字节发送出去,把后面到达的字节缓存起来,当发送方接受到对第一个数据字符的ACK后,再把发送缓存中的所有数据组装成一个报文段发送出去,同时对后面到来的数据进行缓存。只有在收到前一个报文的确认之后,才继续发送下一个报文。规定一个TCP连接最多只能有一个未被确认的未完成的小分组,在该分组的ACK到达之前不能发送其他的小分组。还规定了当到达的数据已经达到发送窗口的一半或者达到报文段的最大长度时,就可以立即发送一个报文段。

接收方只处理了一个数据,缓存只有一个字节时,接收端可以使用延迟ACK的方式,在这期间希望缓存能变大 来处理小包问题
发送方,不理会接收端的小窗口ACK,等小窗口变大后发送。

15.socket 编程中bind的作用,客户端可以bind吗?
绑定地址和端口,用于等待连接和收发网络数据。如果一台机器上有多个IP地址,需要选择一个IP,并且绑定一个端口。
客户端也可以使用bind,但是没有必要,因为操作系统会自动分配。因为服务端绑定的ip和端口是给客户端来连接的,客户端绑定的没有什么实际用途

16.客户端连接已知的服务端,客户端可以开多少连接?(限制:端口号、进程打开文件数量、内存)
理论上,有多少个空闲端口,就可以发起多少个空闲连接。根据TCP/IP协议,端口port使用unsigned short来存储,因此本地端口数量一共有2的16次方(65535)个。其中0~1023是预留端口,不是root用户无法使用,所以理论上应该是65535-1024=64511个,(linux默认文件描述符是1024个,需要修改到65535)。
那么server端能接收最大tcp连接数量是多少呢,理论上是无上限的。因为server端的ip和端口是独占的,不会再需要系统分配新的端口,所以没有端口的限制。操作系统使用4元组来标识一个TCP连接{local ip, local port, remote ip, remote port},其中local ip, local port是固定的,所以我们只需要考虑remote ip和remote port的数量即可, remote ip 32个字节,remote port 16个字节,所以最大连接数量应该是232 * 216 = 248。最大接收不同ip数量 = 232

17.http报文格式
请求行(request line), 请求头部(header), 空行, 请求数据 4个部分组成
请求行包括:请求方法,URL,协议版本信息 (如 GET /admin_ui/rdx/core/images/close.png HTTP/1.1)
请求头部:key-value值 如:
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)
空行(CR+LF):请求报文用空行表示header和请求数据的分隔
请求数据:GET方法没有携带数据,POST方法会携带一个body
回包格式:
状态行:HTTP版本号,状态码和状态值 如:HTTP/1.1 200 OK
响应头:类似请求头,一系列key-value值
空白行:同请求
响应体:响应data

18.tcp怎么保证可靠
1.效验和:TCP效验和由发送端计算,然后由接收端验证,目的是为了发现TCP首部和数据在发送到接收端之间发生的任何改动。如果接收方检测到效验和有错,则TCP段会被直接丢弃。TCP效验和是必须的,UDP效验和是可选的。
TCP和UDP都添加12个字节的伪首部(源IP地址,目的地址,保留字节,传输层协议号(TCP是6),TCP报文长度(报头+数据))
2.确认应答和序列号:保证可靠性,当接收到的数据少了某个序号的数据时,能马上知道;保证数据的按序到达;提高效率,可实现多次发送,一次确认;去除重复数据。TCP首部中有一个标志位-ACK,次标志位表示确认号是否有效。
3.超时重传:当报文发出一定时间内未收到接收方的确认,发送方会进行重传。包丢失,直接再发,ack丢失,再发送后,接收方回ack,并将包丢掉。超时重传时间动态设置为稍大于数据一个来回所用的时间。
4.连接管理:3次握手,4次挥手
5.流量控制:如果发送速度太快,接收方缓冲区满了,发送方继续发送,会丢包。因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。在TCP报文首部有一个16位的窗口长度,接收端接收到数据后,在应答包ACK中将自身缓冲区的剩余大小,写入此窗口。发送方通过此ACK包,值越小,发送越慢。如果为0,发送方暂停发送,但是会定期发送一个探测包,使接收端把窗口大小告诉发送端。
6.拥塞控制:如果网络非常拥堵,此时再发送数据就会增加网络负担,且发送的数据很可能超过最大生存时间也没有达到接收方,就会产生丢包问题,为此,TCP引入慢启动机制,先发出少量数据,像探路一样,搞清楚当前网络拥堵状态后,再决定发送速度。(速度线性上升)

19.业务访问时,返回错误码,怎么排查问题?
首先查看错误码具体定义,根据定义查找相关业务代码。

20.自己的模块,qps(每秒查询率) 有原来的一万多降到一百多,怎么排查问题?
逐级打印消耗时间,从大到小,采用二分法逐级查找。

21.怎么查看程序消耗的系统资源?
windows 任务管理器 linux top命令

标签:ACK,报文,20210531,TCP,发送,服务器,客户端
来源: https://blog.csdn.net/qq_35927741/article/details/117420591