10.20 TCP 协议 和高并发 - 操作系统数据库 复习完】
10.21 上午C++语法 下午复习全部+阿里题目百度
TCP/IP 协议部分--->socket编程--->epoll select--->lighttpd / enginX.
一:链接建立 ,长链接(keep alive),短链接, 双向建立
如何设置为长连接?如何取消
链接建立客户端发送SYNC报文(占用一个序列号),服务器端回传ACK + 期望序列号和自己的SYNC报文(占用一个序列号),然后客户端回传ACK报文(不占序列号)。
长连接:即链接建立 --- 发送数据--链接保活(2h+75s间隔发送若干次)---发送数据--。。 链接终止
保活定时器:2h开始发送,75s间隔发送10次,遇到数据流则重置
1)C挂掉或者网络不好,则连接关闭2)C已经重启则连接重置(关闭)3)C正常,则继续保活。
短链接:链接建立 -- 发送数据-- 链接终止。
交互信息:MSS 窗口大小 SYNC号码
双向同时链接:客户端收到服务器对其SYNC的确认之前收到了服务器单独的SYNC,则此时双向分别发送ACK即可。
从socket上看:
当客户端调用connec之后,发送sync报文;同时server端在listern调用之后协议栈内部建立两个队列,一个是sync报文序列一个是ack序列,当收到sync报文时,sync报文入队列,当收到对应的ack时,则把该队列中的数据取出来放到ack序列队列里面供accept函数返回使用。
1 收不到C发来的ack时,S端会重传sync+ack。里面有两个概念,第一是sync队列的大小,第二是重传时间即超时时间。
另外,若accept队列满了,S收到C的sync+ack,链接会建立吗?
不会,要么丢弃,要么回传C一个rst报文,处理方式由 /proc/sys/net/ipv4/tcp_abort_on_overflow确定。
DOS攻击sync洪泛:由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN 请求
二:发送 接收
窗口有三个一个的对方发来的窗口window(流量控制),一个是本地拥塞窗口cwnd(拥塞控制),一个是ssh65535阈值。
(1)慢启动:
开始时,cwnd = 1(1个mss),每次收到一个ack则cwnd+1,因此收到一个RTT的时候,cwnd加倍。但是cwnd还是要小于窗口时才能发送这么多。
(2)拥塞避免:
当cwnd大于ssh时,每次收到一个ack则cwnd+=1/cwnd,即收到一个RTT的时候,cwnd只加一个。从指数增长变成线性增长。
(3)拥塞发生:
拥塞发生分两种情况,一种是收不到超时时也收不到ack,一种是收到对方连续的ack
(4)拥塞控制 & 快速重传:
1 RTT 超时,则ssh为cwnd的一半,cwnd为1,执行慢启动
2 重复3ack,则ssh为cwnd的一半,cwnd=ssh+3倍报文段大小,执行拥塞避免的算法,即快速恢复。
(5)一般状态下的重传机制?
重传定时器
------------ 以下针对交互式数据流,最终能否发送还要看上面的case--------------
(6)nagle算法(延迟发送):如果存在任何未确认的数据就不能发送小数据包,在此过程中,数据在发送缓存中缓存累积
其初衷:避免发送大量的小包。Nagle算法要求数据必须是“乒乓型”的
即保证网络上只有一个小包在传输(小于mss)。算法默认生效,需要配置TCP_NODELAY关闭nagle算法。
另外,urg模式、FIN包在nagle算法中不生效。
Nagle虽然解决了小封包问题,但也导致了较高的不可预测的延迟,同时降低了吞吐量。
适用于发送大批量数据,对于网络游戏则不适用。
(6)TCP_CORK 延时200ms再发送,初衷则是不发送小包,只发送大包和不得不发送的小包
(7)延时确认Delayed Ack(默认40ms):
延迟确认和nagle混合场景:S发给C一个小数据包,S等C确认后才能发第二个包,但是由于C的延迟确认机制,导致S的第二个包延迟发送。
此时不仅不能减少网络小包数量,更加增加延时。
延迟确认和拥赛避免:S给C发送一个报文进入慢启动过程,但是由于C延迟确认机制导致S端新报文的发送有延迟。
TCP_QUICKACK选项是需要在每次调用recv后重新设置的。
(8)糊涂窗口综合症 坚持定时器
当窗口从0到非0时,接收端发送一个ack给发送端,但是ack可能会丢失,因此双端互等。解决方法是发送端持续在坚持定时器超时时候去探测窗口大小。60s一次。
即通告小窗口-发送小窗口- 避免手段:
1:接收方:不通告小窗口,除非增加了一个MSS或者buffer一半
2:发送方:1>延迟到MSS再发2>至少达到窗口一半再发3>发送不希望ACK的数据
三:链接终止
close 在多线程进程下使用的区别?
单进程/线程和多线程是一致的,多进程下,close一个套接字只是减少一个引用,当引用为0的时后才真正关闭
shutdown则直接关闭。(共享下的问题?)
close和shutdown的区别?
close是关闭双向链接,shutdown只是单向的当然也可以是双向。
close监听套接字和流量套接字的区别?
监听套接字:1:删除保活定时器;2:所有半链接发RST报文
流量套接字:1:释放未读消息(发RST)2:发送所有未发的消息3:发FIN包4:未配置或SO_LINGER超时或者受到了FINACK则结束
shutdown监听套接字和流量套接字的区别?
监听套接字:shutdown写无意义,shutdown读则和close一致
流量套接字:shutdown读只设置标记,shutdown写则和close一致(除SO_LINGER)
在close的时候,若还有未读消息如何处理,未写消息呢?
未读的丢弃,未写的发出。
2MLS定时器?
四:相关命令,抓包分析,代码分析。
TCP协议相关命令:
五:epoll select 和 lighttpd
五种IO模型:
阻塞io =
非阻塞io 不好因为需要cpu不断轮询
驱动模型=
io复用以及
纯异步io=
epoll ET的时候必须是非阻塞。
六:高并发相关
apache 的优点在于进程数的可伸缩性,随着连接数的变化而变化,缺点在于连接数大时会吃掉太多内存。
nginx优点在于所用内存很少,但是事件需要顺序执行,伸缩性上不如apache.
所以大并发服务器在响应速度与内存上必须要兼顾,当然还要是响应速度的重点,因为一切都是为了QPS。
如果内存宝贵,可以采用nginx的epoll 方式,事件按顺序执行,并且不建长连接。
如果内存宽裕,可以采用apache方式,伸缩性会好一些。
高并发库的学习
操作系统相关
http://blog.csdn.net/shreck66/article/details/47102297
数据库相关sqlite
sqlite3相关:
1 单线程模式,2 多线程模式 3 序列化模式 目前实现是多线程模式+互斥锁
优化方法:
1-->加锁 加锁范围缩减或者换锁
2-->操作发送到一个线程,包括读写