正文
下面这个动图,是我们平时客户端和服务端建立连接时的代码流程。
![8c198c3a745bdf1038abb819e91c0eb7.jpeg](https://i-blog.csdnimg.cn/blog_migrate/cc667f3153fbf7f2bafaf92151a13af5.jpeg)
对应的是下面一段简化过的服务端伪代码。
int main(){
/*Step 1: 创建服务器端监听socket描述符listen_fd*/
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
/*Step 2: bind绑定服务器端的IP和端口,所有客户端都向这个IP和端口发送和请求数据*/
bind(listen_fd, xxx);
/*Step 3: 服务端开启监听*/
listen(listen_fd, 128);
/*Step 4: 服务器等待客户端的链接,返回值cfd为客户端的socket描述符*/
cfd = accept(listen_fd, xxx);
/*Step 5: 读取客户端发来的数据*/
n = read(cfd, buf, sizeof(buf));
}
估计大家也是老熟悉这段伪代码了。
需要注意的是,在执行listen()方法之后还会执行一个accept()方法。
一般情况下,如果启动服务器,会发现最后程序会阻塞在accept()里。
此时服务端就算ok了,就等客户端了。
那么,再看下简化过的客户端伪代码。
int main(){
/*Step 1: 创建客户端端socket描述符cfd*/
cfd = socket(AF_INET, SOCK_STREAM, 0);
/*Step 2: connect方法,对服务器端的IP和端口号发起连接*/
ret = connect(cfd, xxxx);
/*Step 4: 向服务器端写数据*/
write(cfd, buf, strlen(buf));
}
客户端比较简单,创建好socket之后,直接就发起connect方法。
此时回到服务端,会发现之前一直阻塞的accept方法,返回结果了。
这就算两端成功建立好了一条连接。之后就可以愉快的进行读写操作了。
那么,我们今天的问题是,如果没有这个accept方法,TCP连接还能建立起来吗?<