网络编程4:PosixAPI和网络IO相关理论

一、什么是PosixAPI?

简而言之,就是Linux操作系统为应用层封装好的统一的接口,用于网络编程、文件处理、进程管理等。

二、建立链接。

1、socket

        socket主要做了两件事情:

        a、分配一个网络IO的文件描述符;

        b、分配一个网络IO的tcb控制块。

socket函数返回一个文件描述符,通过这个文件描述符操作内核中的一个内存。网络通信就是以来这个文件描述符完成。

2、bind

        bind用网络IO的fd,找到对应的tcb,然后设置需要的ip和port。

        对于客户端而言,如果没有使用bind,那么系统会随机分配一个port。

3、listen

        listen主要做了两件事:

        a、创建tcb,并初始化tcb的status为TCP_STATUS_LISTEN。

        b、调整tcb的队列,包括半连接队列和长连接队列。

4、三次握手

简单说:A发syn;B收A发的syn,B再回ack+syn;A收B发的ack+syn,再回ack。

上面的SYN和ACK是协议的两个bit位:

发送端,当发送请求时SYN置1,并随机给一个Sequence Number;

接收端,接收到请求后SYN、ACK置1,并把发送而来的Sequence Number+1返回,然后发送一个随机的Acknowledgment Number;

发送端,接收到接收端发送的Acknowledgment Number后,ACK置1,把发送而来的Sequence Number+1返回。

还有一种情况就是TCP做P2P,互相发送请求,互相接收,本质和上面的情况是一样的,都是按照上面的流程。

三次握手里面,Sequence Number是一个随机数,而Acknowledgment Number是Sequence Number+1。

发送端的状态变化:CLOSED->SYN_SEND->ESTABLISHED,

接收端的状态变化:CLOSED->SYN_RECV->ESTABLISHED。

三次握手是TCP是建立可靠连接的关键步骤,保证TCP连接的应用层不丢失、不重复、不乱序。

5、与三次握手相关的事项

从上图可以看到三次握手时,listen函数:

当接收到syn时,创建tcb并放在半连接队列中;当再次接收到ack时,把半连接队列里面的tcb移动(move)到全连接队列中。

accept函数:

给发送端的TCP分配一个fd,然后把这个fd与全连接队列里指定的tcb建立映射关系。

有三个问题:

a、TCP连接的生命周期从哪里开始?

答:从接收端收到syn创建tcb开始。

b、发送端发送ack时,从半连接队列里面如何找到对应的tcb?

答:根据四元组(source port、source ip、destination port、destination ip)。

c、listen的backlog如何理解?

答:抽象笼统的解释backlog就是tcb的队列长度。

这里说tcb的队列长度也不够准确,因为这跟linux系统的迭代相关,从老版本到现在版本大概经历了三次时期:

表示syn_queue(半连接队列)长度;

表示syn_queue和accept_queue(全连接队列)未被分配fd的tcb数量;

表示accept_queue长度。

最老的版本里通过控制半连接长度,从某种程度上说,这可以部分解决syn泛洪问题,但是随着防火墙、TCP SYN Cookies等技术发展,这个已经不太需要了;现在更看中的是容纳稳定连接的数量,所以就有了第二和第三个版本。

有个非常容易混淆的点要理清楚:backlog指定了等待队列的最大长度,即已完成握手但尚未被accept函数处理的连接请求的最大数量。限制backlog并不是限制并发连接数,它仅限制了在accept函数处理之前的连接请求队列的长度。

三、进行传输

发送端通过send或者write把数据从应用层拷贝到内核,至于数据如何发何时发,都是内核的事情;然后内核把数据按照MTU的上限组成一个包发送;协议栈接收到数据后,通过recv和read都是把数据从内核拷贝到应用层。

1、为什么调用send或者write,调用recv和read有一样的效果?

答:因为send或者write都是通过调用fd把数据从应用层拷贝给内核,而recv或者read都是通过fd把数据从内核拷贝到应用层。

2、再拷贝同样的数据量时,recv一次调用,和recv多次调用有何区别?

答:理论上recv多次调用会增加系统开销,数据拷贝的效率降低。但是实际使用二者区别不大。

3、TCP协议是哪部分?

答:从图上看,TCP协议是用来描述从发送端内核到接收端内核这一段过程的。

四、断开连接

1、close做了哪些工作?

答:首先回收分配的fd,然后向被动方发送一个空包。

2、close和shutdown的区别?

答:close可以关闭主动方和被动方的fd,而shutdown只是关闭本端,不能关闭被动方,开发中不要使用shutdown。

3、主动方先收到ACK后收到FIN,发送方的状态是什么样的?

答:发送方状态先变成CLOSEING状态,再收到FIN之后编程FIN_WAIT2状态。

4、主动方和被动方同时调用close函数?

答:状态如图所示,先编程状态FIN_WAIT1,然后CLOSING,再TIME_WAIT,最后CLOSE。有时候服务器出现大量的TIME_WAIT,可能与双方同时调用close有关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值