本文源自于个人github仓库:https://github.com/forthespada/InterviewGuide
github仓库内有PDF版本下载方式,欢迎各位star、fork~
立志收录计算机校招、社招面试最全面试八股文,无内鬼来点八股文~
81、对于FIN_WAIT_2,CLOSE_WAIT状态和TIME_WAIT状态?你知道多少?
FIN_WAIT_2:
半关闭状态。
发送断开请求一方还有接收数据能力,但已经没有发送数据能力。
CLOSE_WAIT状态:
被动关闭连接一方接收到FIN包会立即回应ACK包表示已接收到断开请求。
被动关闭连接一方如果还有剩余数据要发送就会进入CLOSED_WAIT状态。
TIME_WAIT状态:
又叫2MSL等待状态。
如果客户端直接进入CLOSED状态,如果服务端没有接收到最后一次ACK包会在超时之后重新再发FIN包,此时因为客户端已经CLOSED,所以服务端就不会收到ACK而是收到RST。所以TIME_WAIT状态目的是防止最后一次握手数据没有到达对方而触发重传FIN准备的。
在2MSL时间内,同一个socket不能再被使用,否则有可能会和旧连接数据混淆(如果新连接和旧连接的socket相同的话)。
82、你了解流量控制原理吗?
目的是接收方通过TCP头窗口字段告知发送方本方可接收的最大数据量,用以解决发送速率过快导致接收方不能接收的问题。所以流量控制是点对点控制。
TCP是双工协议,双方可以同时通信,所以发送方接收方各自维护一个发送窗和接收窗。
发送窗:用来限制发送方可以发送的数据大小,其中发送窗口的大小由接收端返回的TCP报文段中窗口字段来控制,接收方通过此字段告知发送方自己的缓冲(受系统、硬件等限制)大小。
接收窗:用来标记可以接收的数据大小。
TCP是流数据,发送出去的数据流可以被分为以下四部分:已发送且被确认部分 | 已发送未被确认部分 | 未发送但可发送部分 | 不可发送部分,其中发送窗 = 已发送未确认部分 + 未发但可发送部分。接收到的数据流可分为:已接收 | 未接收但准备接收 | 未接收不准备接收。接收窗 = 未接收但准备接收部分。
发送窗内数据只有当接收到接收端某段发送数据的ACK响应时才移动发送窗,左边缘紧贴刚被确认的数据。接收窗也只有接收到数据且最左侧连续时才移动接收窗口。
83、建立TCP服务器的各个系统调用过程是怎样的?
服务器:
创建socket -> int socket(int domain, int type, int protocol);
domain:协议域,决定了socket的地址类型,IPv4为AF_INET。
type:指定socket类型,SOCK_STREAM为TCP连接。
protocol:指定协议。IPPROTO_TCP表示TCP协议,为0时自动选择type默认协议。
绑定socket和端口号 -> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:socket返回的套接字描述符,类似于文件描述符fd。
addr:有个sockaddr类型数据的指针,指向的是被绑定结构变量。
// IPv4的sockaddr地址结构 struct sockaddr_in { sa_family_t sin_family; // 协议类型,AF_INET in_port_t sin_port; // 端口号 struct in_addr sin_addr; // IP地址 }; struct in_addr { uint32_t s_addr; }
- addrlen:地址长度。
监听端口号 -> int listen(int sockfd, int backlog);
sockfd:要监听的sock描述字。
backlog:socket可以排队的最大连接数。
接收用户请求 -> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd:服务器socket描述字。
addr:指向地址结构指针。
addrlen:协议地址长度。
注:一旦accept某个客户机请求成功将返回一个全新的描述符用于标识具体客户的TCP连接。
从socket中读取字符 -> ssize_t read(int fd, void *buf, size_t count);
fd:连接描述字。
buf:缓冲区buf。
count:缓冲区长度。
注:大于0表示读取的字节数,返回0表示文件读取结束,小于0表示发生错误。
关闭socket -> int close(int fd);
fd:accept返回的连接描述字,每个连接有一个,生命周期为连接周期。
注:sockfd是监听描述字,一个服务器只有一个,用于监听是否有连接;fd是连接描述字,用于每个连接的操作。
客户机:
创建socket