15阶段结论整理

2个大原则

1 read只是拷贝不是接收

2 write只是拷贝不是发送

第14篇文章的案例——发送端使用默认发送缓冲区大小,接收端不read,即能证明这两点,前12秒接收端没read,包也过去了直到窗口不够,而此时发送端一直继续write,虽然包没出去

 

 

1关于tcp delayedack实践(一)tcp

通过实践,用hello world\r\n模型,通过抓包,验证了nagle+delayed ack的情况,观察到linux和mac的默认delayed ack时间为40ms

证明了flush不能打破nagle

证明了quickack的存在,所以猜测http 短链接不会有nagle+delayed ack

 

2关于tcp delayedack实践(二)http

验证了http请求3次握手和4次挥手

证明了http短链接不会有delayed ack,http长连接第3次请求开始delayed ack

 

4socket缓冲区与沾包 nagle in tcp

实践了导致沾包是在发送端还是接收端,验证了只有2个包的情况下,即使启用nagle,发送端也不会沾包,沾包必然是接收端导致(nagle1)

hello模型,5个字母分开发,2个包以上,启用nagle,发送端可沾包

证明了fin包可打破nagle,导致连续2个包出去,未等待ack

 

5netty(十八)《netty粘包消息定长 实践》中,沾包哪里来的?nagle in netty

证明了netty禁用nagle情况下,发送端不会沾包,接收端沾包

证明了nagle禁用情况下,包可以连续发而不等待ack

验证了netty默认禁用nagle

证明了,启用nagle情况下对netty连发5个包的情况,2个包以上,发送端会沾包

 

10tcp缓冲区大小设置

证明了java socket receive buffer 即是 tcp 接收窗口

验证了linux 默认接收窗口不是8k,最大值也不是65536

实践了以100设置为SO_RCV_BUF,系统会放到1100-1400

centos7.5默认接收40k,发送8k

 

11读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(一) 【重点】

证明了接收窗口不够时,一些情况会导致write阻塞,但不是直接因为对端接收窗口不够了,而是因为对端窗口导致本方发送缓冲区积压至满,只要内核发送缓冲区够大,write就能返回,不会由于对端不接收数据而直接阻塞

实践了对端接收窗口不足时,本方会拆包发送;对于500+的接收窗口,会先拆包后直接发送,对于500-的接收窗口,会等5s然后再拆包发送

实践了对端接收窗口为0时,本方每隔5s询问一次

再次验证了quick ack与delayed ack

证明了即使接收端不read(实际是不从kernel copy到用户态),也会返回ack

证明了发送缓冲区==包大小情况下,即使启用nagle,发送端不会沾包(nagle2)

再次验证了启用nagle情况下对socket连写5个包的情况,2个包以上,发送端会沾包,当然此时发送缓冲区!=包大小

证明了write只是将用户态拷贝到内核发送态,不会保障会立即发送甚至是否会发送

再次证明了nagle禁用情况下,包可以连续发而不等待ack

实践了禁用nagle也会受到接收窗口的限制,不会毫无限制异步发送

 

12读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(二)

实践了接收方窗口重新恢复后,会主动发包通知发送方 

 

13发送缓冲区、滑动窗口 对小于mss的包是如何拆包的

证明了 发送缓冲区<包<MSS && 发送缓冲区<对端接收窗口 时,按发送缓冲区拆包

实践了全程无delayed ack的情况

证明了 发送缓冲区>包>接收窗口 && 包<MSS,按接收窗口拆包

再次实践了对端接收窗口不足时,本方会拆包发送;对于500+的接收窗口,会先拆包后直接发送,不会像“对于500-的接收窗口,会等5s然后再拆包发送”延迟5s

 

14读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(三)

证明了禁用nagle情况下,并非所有情况下发送端都不会沾包(nagle3)

再次证明了接收窗口不够时,一些情况会导致write阻塞,但不是直接因为对端接收窗口不够了,而是因为对端窗口导致本方发送缓冲区积压至满,只要内核发送缓冲区够大,write就能返回,不会由于对端不接收数据而直接阻塞

再次证明了write只是将用户态拷贝到内核发送态,不会保障会立即发送甚至是否会发送

证明了程序正常结束后tcp连接还会继续保持(本例中,抓包显示程序结束后还有大量包往来)

证明了程序正常结束时,程序隐式close socket(本例中,抓包显示客户端程序结束时拟发送fin包,尽管由于缓冲区堆积未立即发送)

证明了默认SoLinger为false,close socket时,会等待发送缓冲区发完后发fin包四次挥手

 

16大于mss的包是如何拆包的

证明了 对方窗口>包>MSS && 发送缓冲区>包,按MSS拆包

 

17tcp close端口占用 & setReuseAddress 【本地】

实践验证了客户端-服务端短链接中的端口已占用问题导致第2次client连接请求驳回现象

再次证明了程序正常结束后tcp连接还会继续保持,进程即使没了,连接和端口占用仍然在(不占用就不会有冲突)

证明了setReuseAddress对于Fin_wait2 和time_wait均没用(mac)都有用(linux)

证明了一端不显式close socket或关闭进程,不会发出fin包响应另一端的fin包

再次证明了程序正常结束会隐式close socket,(本例中正常结束的客户端端口处于time_wait,所以它是close主动方)

证明了客户端也可以绑定端口

 

18读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(四)

再次证明 默认SoLinger为false

证明了close socket时,发fin还是rst,什么时候发,发之前是否先等缓冲区全部发送完,由tcp协议Linger参数控制

证明了linger为true时,显式或隐式(程序正常退出)close socket,直接RST包,无视发送缓冲区的待发送内容,然后就没有然后了

验证了发出RST包,对端无需ack

验证了一端rst另一端后,另一端read,报connection reset

 

19connection reset rst fin linger(一)

再次证明了程序正常结束后tcp连接还会继续保持

实践验证了一端rst,另一端读写,将connection reset(by peers) or broken pipe exception

A端close,另一端读,无事,另一端写,A端rst

证明了rst包一经发出,netstat nothing,端口和连接完全释放,没有time_wait fin_wait

再次证明了发出rst包,对端无需ack

再次证明了即使接收端不read(实际是不从kernel copy到用户态),也会返回ack

证明了socket.isClosed没用

 

20connection reset rst fin linger(二)

再次侧面证明了程序结束会隐式close,等同于显式close(因为程序自然结束抓包===程序结束前close)

证明了close发fin包,而且不再接收,不能完全适用于tcp4次挥手

证明了socket.shutdownOutput 会且只会发fin包,不会拒绝接收,更契合tcp协议4次挥手

证明了程序结束会隐式close,覆盖shutdownOutput

建议主动关闭端使用shutdownOutput,以更好的契合tcp四次挥手

 

22文件描述符耗尽(一)mac【本地】

0 证明了mac系统默认所有进程(系统级)12288,单进程(用户级)10240

1 mac环境下,立足系统级(虽未触达用户级,但触达系统级),通过纯文件、纯socket、socket+文件3种方式验证了文件描述符耗尽导致too many open files in system 

2 mac环境下,立足系统级,证明了系统级fd耗尽除了socket与纯file,还会影响本进程类文件读取、其它进程如terminal打开、jps命令执行、idea的运行、java make、lsof命令,甚至导致系统不可用

3 mac环境下,立足系统级,通过socket+文件方式验证了socket导致的too many open files 同样会继续影响到后续程序纯文件读取,证明是socket和纯file是同一个文件的概念

*mac系统级较小,用户级较大

 

23文件描述符耗尽(二)linux【本地】【重点】

0 证明了centos 7.5 系统默认所有进程(系统级)183945,单进程(用户级)10w

1 linux环境下,立足用户级(未触达系统级,但触达用户级),通过纯文件、纯socket、socket+文件3种方式验证了文件描述符耗尽导致too many open files in system 

2 linux环境下,立足用户级,通过socket+文件方式验证了socket导致的 too many open files 同样会继续影响到后续程序纯文件读取,证明是socket和纯file是同一个文件的概念

3 验证了Closeable接口会自动调用close

4 实践了linux环境 lsof -p port|wc -l的值可能比ulimit -n大

5 实践了FIN_WAIT2不占用文件描述符 

*linux用户级可设置为较小,系统级较大

 

24netty(二十)http代理服务器

证明了浏览器同一时刻同一host 6个连接

证明了浏览器的http连接是同步阻塞的,一条连接上一个请求没有返回response之前,不会发出下一个请求,各请求-响应生命期不重叠

实践了长连接中,chunked和length需要其一,也只需要其一(postman冲突),否则导致浏览器阻塞;用短链接则不需要设置那两个header

实践了是存在多个同名http header的

实践了破解header_token+cookie的csrf防御

 

27读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(五)linger 3s

linux下,也会根据对端窗口拆包

so_linger 3s mac与linux下都没用,过了3s即使发送缓冲区还有积压,也没发rst而是发fin,无论显式还是隐式close

 

28读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(六)

证明了linux下,tcp协议的实现对每个channel都有一个接收缓冲区

 

29java socket模拟http【重点】springboot json post bug,wireshark抓http包

验证了java socket可以模拟http请求

证明了netty http无论长短连接都需要content-length参数,对http协议的粘拆包起控制作用

 

30multipart/form-data和application/x-www-form-urlencoded的区别(二)urlencoded之自动deocde

以java socket证明了springboot tomcat对body,允许直接发送utf8编码二进制,无需urlencode,符合http1.1协议二进制body的原则;tomcat会自作多情decode一下

对于http uri,需要urlencode

 

====== 

注释:

nagle1:启用,2个包,发送端不沾包

nagle2:启用,发送缓冲区==包大小情况下,发送端不沾包,但发送端很有可能write阻塞

nagle3:禁用,接收窗口定时阻塞,发送端等,发送端沾包,这个等待,与nagle启用等ack同样性质,也导致了同样的结果,就是后面的包搞在一起(当然如果发送缓冲区==包大小情况无此担忧,会直接阻塞)

 

 

 

=======

yet

tcp尾声:

滑动窗口协议、拥塞控制、流量控制、慢启动、RTT,结合tcp顺序重组,理论过一过就行,结合一下限流滑动窗口法  8tcp为什么是可靠的,tcp如何保证顺序【重点】

tcp有机会的话结合一下那片tcp过程详细的文章,seq与len,糊涂窗口  8tcp为什么是可靠的,tcp如何保证顺序【重点】

tcp异常,tcp的一些linux参数reuse recycle linux tcp性能参数【yetdone】  tcp_tw_recycle tcp_tw_reuse与timewait【yetdone】 

tcp队列长度与tcp cookie,洪水攻击、半链接 tcp_syncookies 半连接

一次完整的http 25一次http完整流程【yetdone】

ip分片与路由节点(手机收藏图)

 

netty

netty高低水位(netty高低水位流控(yet)),netty boss worker(boss与worker

netty buf与cas(netty高低水位流控(yet)),buffer是channel共享的?netty如何将tcp收到的消息塞入rcf buffer的?可能还要结合nio

netty内存,结合2本书(netty之堆内存、直接内存、bytebuf(yet)

netty线程模型整理图,结合nio

tcp 内核原理流程-结合25一次http完整流程【yetdone】,0拷贝、内存映射共享、文件锁,netty的0拷贝体现在哪里

netty源码结合nio源码:http://www.iocoder.cn/Netty/Netty-collection/?zhihu

为什么要用netty:https://youzhixueyuan.com/netty-implementation-principle.html?from=singlemessage&isappinstalled=0,一次netty与java socket的压力测试对比【yetdone】为什么要用netty

 

posted on 2019-12-15 12:59  silyvin  阅读(220)  评论(0编辑  收藏  举报