cs流程类似于接电话的过程,如果你想打电话就需要有一个手机,这时候就需要用一个socket函数,调用后返回一个sockfd文件描述符,用来标记这个服务器的的一头,也就是手机,文件描述符是连接作用,并不能交互信息,
然后绑定电话卡,将你的手机里面插进电话卡,也就是bind函数的作用,将sockfd绑定服务器的端口和ip地址,这样有地址了客户就可以知道是和谁进行联系,进行交互,而客户端则不需要进行bind绑定,因为你给我打电话我不需要知道你的电话是什么,我只管接数据就行,谁都可以给我打,
紧接着就是使用listen函数使得sockfd成为一个可被监听的状态,从一个未连接的描述符变成一个已经连接的描述符,此时就可以和客户端进行连接,开始被动等待客户端的信息,客户端通过connect函数将客户端的sockfd变成一个可以连接的描述符,然后给客户端发送请求,内核开始自动进行三次握手,握手成功失败connect会自动返回,握手成功的则被放在listen队列中,
listen() 函数的主要作用就是将套接字( sockfd )变成被动的连接监听套接字(被动等待客户端的连接),至于参数 backlog 的作用是设置内核中连接队列的长度,TCP 三次握手也不是由这个函数完成,listen()的作用仅仅告诉内核一些信息。这里需要注意的是,listen()函数不会阻塞,它主要做的事情为,将该套接字和套接字对应的连接队列长度告诉 Linux 内核,然后,listen()函数就结束。处于被连接监听状态的,这样的话,当有一个客户端主动连接(connect()),Linux 内核就自动完成TCP 三次握手,将建立好的链接自动存储到队列中,所以,只要 TCP 服务器调用了 listen(),客户端就可以通过 connect() 和服务器建立连接,是建立了连接,就是打通了 但是有没有接受客户端想要通信这个请求不是这个函数决定的,三次握手成功就代表同意,然后就开始接受,accept之后就可以通过文件描述符来通信了。如果没有请求,就会一直阻塞,只到有请求。而这个连接的过程是由内核完成。就是例子中可以打电话了,但是打电话需要交流,怎么交流就需要通信了
accept()函数功能是从处于 established 状态的连接队列头部取出一个已经完成的连接,如果这个队列没有已经完成的连接,accept()函数就会阻塞,直到取出队列中已完成的用户请求为止。此时返回一个acceptfd来进行交互信息,客户端通过write将数据写入sockfd中,从这个客户端的出口出发去往服务端,然后服务端用返回的acceptfd来通信 将acceptfd缓冲区中的数据读到buf中,再将buf中的数据写入acceptfd,送回到客户端。read和write有将数据发送到客户端或者接受客户端的消息的功能,acceptfd是一个中间量来通信
用于与客户端进行实际的通信。\n目的:当服务器监听到客户端的连接请求后,通过accept函数从监听套接字的等待队列中取出一个连接请求,并返回一个新的套接字(即已连接套接字),用于与客户端进行数据的发送和接收。
目的:通过调用listen函数,服务器告诉内核该套接字是被服务器而不是客户端使用的,并进入被动监听状态,等待来自客户端的连接请求。
从队列中取出一个请求就返回一个已连接套接字用来和客户端进行通信