共计 1214 个字符,预计需要花费 4 分钟才能阅读完成。
记录 unix 网络编程的复习之路
简单回顾下 socket 连接过程
-
socket() – 得到 fd!
功能:指定了协议族 (IPv4、IPv6 或 unix) 和套接口类型(字节流、数据报或原始套接口)。但并没有指定本地协议地址或远程协议地址。定义:int socket(int family, int type, int protocol); 返回:出错:-1 成功:套接口描述字 (socket file descriptor)(套接字)sockfd
-
bind() – 我在哪个端口?
功能:给套接口分配一个本地协议地址。定义:int bind(int sockfd, const struct sockaddr *my_addr, int addrlen);
-
connect() –Hello!
功能:建立与 TCP 服务器的连接 定义:int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
-
listen() – 有人给我打电话吗?
功能:将未连接主动套接口的转换为被动套接口,指示内核接受对该套接口的连接请求。定义:int listen(int sockfd, int backlog); 参数:- sockfd 调用 socket 函数返回的文件描述符(套接字). - 未完成连接队列和已完成连接队列的上限. - 未完成连接队列 : 服务端还未完成三次握手全部过程的一个队列. - 已完成连接队列 : 服务端已经完成三次握手全部过程的一个队列, 等待 accept 函数从这个队列中返回下一个 (返回其实是取出, 该套接字不在已完成队列中了) 套接字.
-
accept() –“Thank you for calling port 3490.”
功能:accept 函数从 listen 的已完成连接队列中返回下一个已完成连接, 也就是对端的套接字, 一个新的套接字. 当已完成连接队列的下一个完成 连接是空, 那么 accept 函数将被阻塞. 定义:int accept(int sockfd, struct sockaddr *cliaddr, int* addrlen); 返回:调用成功时返回: 1. cliaddr: 客户进程的协议地址和地址大小 2. 新套接口描述字
- send() 和 recv() –Talk to me, baby!
- close() – 滚开!
socket()和 accept()返回的 fd
举个栗子:
一个客户端和一个服务端连接,双方 socket 产生各自的 c_sock_fd 和 s_sock_fd;s_sock_fd 进行 bind 和 listen 后,accept 准备接受客户端的连接请求;c_sock_fd 调用 connect 请求连接服务端;服务端接到请求产生 accept_fd,届时 accept_fd 和 c_sock_fd 两个套接字可以通讯,而 s_sock_fd 则可以关闭;客户端关闭 close(c_sock_fd)后,服务端关闭所有未关闭的 fd,通讯彻底断开。ps:服务端的 socket 产生的套接字只是用来监听的,不能直接用于发送接收数据。
正文完