1:当调用函数connect时, 发出一个SYN, 若无响应, 等待6秒后再发一个, 若仍无响应, 24秒钟后再发一个, 若总共等了75秒钟之后仍未收到响应,则返回错误.
2:有三个条件返回RST, 1:SYN到达某端口, 但此端口没有正在监听的服务器, 2,TCP想取消一个已有连接,3, TCP接受了一个无法识别,或者不存在的连接上的分节.
3:int listen(int sockfd, int backlog)函数, 其中第二个参数规定了内核为此套接口排队的最大链接个数.
其中已完成连接队列标表示三次握手已经建立(ESTABLISHED), 半连接队列表示正在三次握手中,服务端的状态是SEND_RECV,
当来自客户的SYN到达时, TCP在未完成连接队列中创建一个新条目, 然后用三路握手的第二个分即服务器SYN+ACK,这个条目保留在未完成队列中, 知道三次握手完成,或者SYN_ACK重传超时(75秒), 如果三次握手完成, 该条目将从未完成连接队列搬到已完成连接队列的队尾.当进程调用函数accept时, 将已完成连接队列中的队头条目烦恼会给进程, 如果此时队列为空, 进程将睡眠, 直到有条目放入已完成连接队列中.
4: int accept(int sockfd, struct sockaddr *clladdr, socklen_t * addlen)
调用accept接口服务端已经处于ESTABLISHED状态, 该接口被调用时, 表示从已完成连接队列中取出队头的一个连接, 如果接口调用成功将返回一个已完成连接的TCP连接(全新描述符), 后面的发送和接收数据都需要传入该已完成的TCP连接描述符, 而传入该接口中第一个参数sockfd表示该服务器的一个全局唯一的监听socket描述符, 该监听描述符一直存在, 直到服务器关闭才会消失, 而已连接socket描述符(accept返回的)的生命期是连接的生命期, 关闭了连接则该描述符就被内核收回.
5:并发服务器服务器框架?
由上代码, 服务器绑定IP, 端口, 建立监听后, accept会轮询处理客户发过来的连接, 当客户和服务器成功建立连接后, 服务器会创建一个子进程, 由子进程来处理客户的业务(pid == 0), 父进程(pid > 0)则调用close关闭父进程和客户的连接, 子进程中关键监听socketfd, 然后处理客户业务, 业务处理完后, 关闭连接sockfd, 注:此种父进程调用close接口, 并不会关闭连接, 只是将该连接的引用计数减一, 由2减为1, 引用计数不为0, 不会关闭连接, 在父进程Accept拿到该连接时, 引用计数为1, 当创建子进程时, 该连接会被子进程共享, 引用计数加1, 故创建子进程后该连接的引用计数为2, 只有当该连接的引用计数为0时,才会断开连接, 走四次挥手流程.
我们必须意识到, 如果父进程不对每个accept返回的已连接套接口调用close, 并发服务器将会发生什么? 首先, 父进程最终将耗尽可用的描述字, 因为任何进程在某时刻打开描述字数总是有限的, 但更重要的是, 没有个客户连接被终止, 当子进程关闭已连接套接口时, 它的访问计数值由2减为1, 且保持1, 这将导致TCP连接无法终止, 连接永远开放着.
相关文章: