网络原理 -Posix API
思考
- Posix API 有哪些?
- 三次握手的过程 ?发生在什么函数中?
- Accept发生在三次握手的哪一步?
- 数据发送过程怎么解决粘包分包的问题?
- 四次挥手过程?服务器出现大量的
close_wait()
原因? - 被动方, 主动方的tcb的回收是在什么时候?
- websocket 为什么设置
FIN位
? - TCP在
listen
时的参数backlog
的意义?
八种Posix API
Tcp server:1.
socket()
;2.bind()
;3.listen()
;4.accept()
;5.recv()
;6.send()
;7.close()
Tcp client:1.
socket()
;2.bind()
(optional);3.connect()
;4recv()
;5.send()
;6.close()
非必须设置的
socket
参数:setsockopt()
;getsockopt()
。
bind()
的主要作用:接受或者发送数据,用来填充本机的IP与端口。
socket是什么?
socket
:插和座,socket有两部分组成fd
与tcb
,即文件描述符,tcb即tcp控制块,就像插座一样,插就是fd,是文件系统中的文件描述符,可以被“操作的”。tcb在协议栈当中,我们“不需要管”,就像所谓的座,不用管具体是什么样。当操作fd,调用send()
,fd的数据就放到sendbuffer中,当调用recv()
时将recvbuffer中的数据放到fd中。
socket 5元组
站在客户端角度来说socket五元组(
remoteip
,remoteprot,
localip
,localport
,proto
)中remoteip与remoteprot 为远端IP和端口,即服务器的IP和端口,localip与localport为本地IP和端口,即客户端IP和端口,proto是协议。
站在服务器角度来说(source ip
, source port,
dest ip
, dest port
, proto
)中source ip与source port为源IP与端口,即客户端IP与端口,dest ip与dest port 为目的IP与端口,即服务器IP与端口,proto是协议
// socket创建的fd从3开始 //0为stdin,1为stdout,2为stderr int fd = socket(); fd = 3
“一见钟情”与“移情别恋”
三次握手过程
三次握手发生在
connect()
函数里面。connect()类似一个导火索
int clientfd = accept(); 只做两件事情:1、从全连接队列取出一个节点;2、为该节点分配fd放到。 fd -->tcb,通过五元组
数据的发送
为什么会出现粘包
或拆包
以及怎么解决?
粘包粘包 简单的来讲就是接收端收的次数比发送端发送的次数少,出现两个包合在一起的情况。简单说有以下几种情况:
1.TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。
2.接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。
3.待发送数据大于最大报文长度(MMS),TCP在传输前将进行拆包。
4.发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。
简单的来说,TCP
是基于字节流的,即使应用层和TCP传输层之间的数据交互是大小不等的数据块,然而TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界。从TCP的帧结构也可以看出,在TCP的首部没有表示数据长度的字段,基于这两点,TCP传输数据时,才会出现粘包或者拆包现象的可能。
解决方式,简述两种解决思路:1.在协议前加上要传输数据长度。2.加上包的分隔符。
另外,这里还有一个问题,如何保证我们接收的数据是顺序的?所谓的顺序,就是先发的先到。这里要说的就是延迟ack
,它可以保证所谓的“顺序”
。
留一个思考:Tcp已经这么强了,为什么还要有UDP?
四次挥手的过程
主动方调用
close()
函数后,fin
位置1,申请断开连接。
服务器出现大量的close_wait()
原因与解决方式?原因:
1.没有及时调用close()函数。
2.业务逻辑的问题。
简述解决方案: 要么提前调用
close()
,要么将业务信息放在线程池去处理,close放在另一个线程中去处理。
websocket 为什么设置FIN位
?
把业务买用户数据清空,防止出现大量的close_wait(),再完成这些操作以后再调用close()关闭。
思考问题:作为客户端,做一个业务的请求(如http的请求),请求第三方的业务。出现一种情况,客户端一直处于fin_wait2
的状态(可能由于在server端中close之前,服务器掉电客户端直接进入fin_wait2
的状态),要么这个问题就不解,再启动一个连接。如果FIN_WAIT_2的超时时间(tmo)大于TCP_TIMEWAIT_LEN(60秒)的时长,启动keepalive定时器
,定时时长为二者之差(tmo - TCP_TIMEWAIT_LEN)。
client与server同时发送fin的情况
服务器出现大量的
time_wait
怎么做?**简述原因:**应用中产生大量TIME_WAIT状态的根本原因是频繁创建断开连接TCP连接。要解决TIME_WATIT状态过多的问题,就要分析我们的应用把频繁创建的短连接改为长连接。
后台业务服务器,通常需要调用redis、mysql以及其他http服务和grpc服务,在服务相互调用中,如果使用的是短连接,高并发时就会产生大量TIME_WAIT。一般情况下,redis等客户端会有连接池,我们要做的是设置好相关的连接服用参数,一般会有连接数、连接重用时间、连接空闲数等。所以在应用中通过设置合理的连接池参数可以避免TIME_WAIT状态过多的问题。
总结
1)POSIX API八个,
socket()
,bind()
具体作用;2)三次握手的过程,中间发生在哪些API当中,connect()是怎么调用,
listen()
,accept()
是怎么执行;3)数据传输的过程,
send()
拷贝数据到sendbuffer中,内核协议栈决定怎么去发送,recv()
将recvbuffer中将数据拷出来;4)四次挥手,断开连接的过程,
close()
的操作,以及相关过程中遇到的问题。5>
client
与server
同时发送fin。