理解Posix API
理解7个Posix API
POSIX:可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX )。它是一套标准,Unix与Linux和苹果系统的Unix-base都遵循这个标准,话不多说,赶紧进入正题。
socket()
功能:
- 分配一个int型的fd。
- tcb(tcp控制块),由alloc()创建出来;
bind();
功能:
- 将socketfd与ip,port绑定在一起。
listen():
下图为TCP状态转移图,listen的过程就是将状态设置为LISTEN,即 tcp -> status = LISTEN tcp -> seqnum = random() tcp -> acknum = random() 以random值开始计数,下一个数据包的seqnum为random+1,acknum同理。 这里设为随机值的原因是以防攻击者推断出已发的数据包的数量
TCP状态转移图
下图为TCP包,在建立连接的时候(握手)会将ACK与SYN置一,这样就能识别出该数据包是用来握手的。
1
具体这个过程在client端发生在connect() 这个函数中,而server端这个过程是在内核协议栈中,代码不可控,是一个被动的过程。tcp是首先在client第一次与server握手的时候,也即listen的时候,将该连接加入半连接队列中;若想要在后续查找到该连接的方法是通过五元组来进行查找。 syn泛洪攻击的时候,可以通过设置listen函数的第二个参数来进行避免,在两个老版本中,分别表示syn queue的大小,这样做可以有效防止泛洪攻击或syn queue与accept queue大小之和,即未被分配fd的tcb数量,现在的版本则是accept queue的大小,这样做则可以有效增加建立连接的数量,增大吞吐量。 客户端与服务端建立连接的过程(三次握手)如下图所示。
accept():
功能: 分配fd,将fd分配给tcb。 在使用accept函数时,一般是来处理listenfd的情况,且LT时可以做到来一个listenfd接受一个,而在ET的时候则需要用循环来控制:
1
2
3
4
while(1){
fd = accept();
if(fd == -1) break;
}
以上四个API实在建立TCP连接的时候进行使用,下面将介绍传输数据的两个API。
send():
send只是通过本机应用传到本机的内核,内核组织好后,若无延迟,由其通过网络传到远程的内核,内核中做的事情是不知道的,是由协议栈决定。
recv():
而在服务器内核接受到数据后调用recv将内核中的数据传到应用中来。
整个流程如下图所示图中mtu代表最大传输单元。
传输数据的两个API介绍完了,最后还剩下一个断开连接的部分。
close():
功能:fd首先被回收;然后发送fin,在服务端的recv()就会返回0告诉现在要close连接了,然后服务端就也会调用close函数,在这之前会回发一个ack包。后面的流程也同理,服务端回发fin给客户端,客户端也发送ack。这整个流程也可以用上面的TCP状态转移图来理解与分析。




