TCP 通信流程
tcp协议特性:面向连接,可靠传输,面向字节流。
服务端:
- 创建套接字
在内核中创建socket结构体与网卡建立联系,描述协议版本,传输类型,协议类型。 - 为套接字绑定地址信息
给socket描述源端地址信息。 - 开始监听
告诉操作系统可以开始接收客户端的连接请求(客户端与服务端进行TCP通信必须首先建立
连接,确保双方都具有数据收发的能力).
当服务端收到了客户端的连接请求,连接的建立过程都是在内核中完成的。
tcp服务端最早的套接字只用于接收新连接请求,连接请求到来之后创建新的套接字创建的
新的套接字用于和客户端后续的通信。(监听套接字 / 通信套接字) - 服务端程序获取新创建的socket套接字操作句柄
服务端程序在内核中接收到新的连接,会创建新的socket。服务端程序获取内核中新创建
的socket操作句柄,在服务端程序这边通过这个获取的新建的操作句柄和客户端进行通信。 - 服务端通过新建套接字可以与客户端进行数据通信
tcp在数据通信的时候,谁先发送都可以(因为这时候连接已经建立)
发送数据:将数据拷贝到内核socket的发送缓冲区。
接收数据:从内核socket的接收缓冲区中取出数据。 - 关闭套接字:释放套接字
客户端:
- 创建套接字
- 绑定地址信息(不推荐主动绑定)
- 向服务端发送连接请求
- 收 / 发数据
- 关闭套接字
服务端是否开始接收客户端请求,取决于套接字是否开始监听。最早的套接字就像是饭店中的门迎
永远只迎接新顾客,即最早的套接字永远只接收新连接请求,然后为这个新客户端连接创建新的服
务端套接字进行通信,新建的服务端套接字专门用于这一个客户端通信。
socket进行TCP通信的接口
//创建套接字
int socket(int domain, int type, int protocol)
domain: 地址域 AF_INET -> IPV4
type: 套接字类型 SOCK_STREAM 用于tcp通信 SOCK_GRAM 用于udp通信
protocol:协议类型 IPPROTO_TCP
返回值:一个socket操作句柄
//绑定地址信息
int bind(int sockfd, sockaddr* addr, socklen_t len)
//开始监听
int listen(int sockfd, int backlog)
sockfd: socket操作句柄
backlog: 内核中tcp连接pending队列的最大节点数,
决定了同一时刻服务端所能接收的客户端请求数量。
//服务端程序获取新创建的socket操作句柄
int accept(int sockfd, struct sockaddr* addr, socklen_t len);
sockfd: 指定获取哪个服务端socket对于新连接所创建的新套接字socket.(监听套接字)
addr: 客户端地址信息
len: 输入输出型参数,指定想要获取的地址长度,以及获取实际得到的地址信息长度。
返回值:正确返回具体新创建套接字的操作句柄,用于后续与指定客户端通信,失败返回-1
//这是一个阻塞函数,若没有新连接到来则一直等待
//收 / 发数据
int recv(int sockfd, char* buf, int len, int flag);
int send(int sockfd, char* data, int len, int flag);
sockfd:对于服务端来说就是accept返回的新创建的套接字描述符。