TCP通信流程

//TCP通信的流程
//服务器端
1.创建一个用于监听的套接字
 -监听:监听有客户端的连接
 -套接字:这个套接字就是一个文件描述符
2.将这个监听文件描述符和本地的IP和端口绑定(IP和端口就是服务器的地址信息);
  -客户端连接服务器的时候就使用这个IP和端口
3.设置监听,监听的fd开始工作;
4.阻塞等待,当有客户端发起连接,解除阻塞,接收客户端的连接,会得到一个和客户端通信的套接字(fd);
5.通信:接收数据和发送数据;
6.通信结束,断开连接
//客户端
1.创建一个用于通信的套接字(fd);
2.连接服务器,需要指定连接的服务器的IP和端口
3.连接成功,接收数据和发送数据;
4.通信结束,断开连接

TCP通信
TCP通信的过程:

scoket函数
// 创建一个套接字
int socket(int domain, int type, int protocol);
	domain:地址族协议
		AF_INET: IPv4 
		AF_INET6: IPv6
		AF_UNIX,AF_LOCAL:本地套接字
	type:通信过程中的协议类型
		SOCK_STREAM: 使用流式的传输协议
		SOCK_DGRAM: 使用报式传输协议
	protocol: 一般写 0 即可,具体的协议
		SOCK_STREAM: 流式传输默认使用的是 tcp
		SOCK_DGRAM: 报式传输默认使用的 udp
	返回值:
		成功:返回可用于套接字通信的文件描述符,操作的就是内核缓冲区,某一块内存
		失败: -1
//将文件描述符和本地的IP与端口进行绑定   
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
	sockfd: 监听的文件描述符,通过socket()调用得到的返回值
	addr: 传入参数,要绑定的 IP 和端口信息需要初始化到这个结构体中
	addrlen: 第二个参数结构体占的内存的大小
	返回值:成功返回 0,失败返回 - 1
// 监听这个套接字上的连接
int listen(int sockfd, int backlog);
	sockfd: 文件描述符,通过socket()函数得到的文件描述符
	backlog: 未连接和已连接的和的最大值,最大值为4096
	返回值:函数调用成功返回 0,调用失败返回 -1
// 等待并接受客户端的连接请求, 建立新的连接, 会得到一个新的文件描述符(通信的)		
//这个函数是一个阻塞函数,当没有新的客户端连接请求的时候,该函数阻塞;
//当检测到有新的客户端连接请求时,阻塞解除,新连接就建立了,得到的返回值也是一个文件描述符,基于这个文件描述符就可以和客户端通信了。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
	sockfd: 监听的文件描述符
	addr: 传出参数,里边存储了建立连接的客户端的地址信息(IP和端口)
	addrlen: 指定第二个参数的对应的大小
	返回值:函数调用成功,得到一个用于通信的文件描述符,用于和建立连接的这个客户端通信,调用失败返回 -1
// 成功连接服务器之后, 客户端会自动随机绑定一个端口
// 服务器端调用accept()的函数, 第二个参数存储的就是客户端的IP和端口信息
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
	sockfd:客户端通信的文件描述符,通过调用socket()函数
	addr: 客户端要连接的服务器端的地址信息: iP 和 端口
	addrlen: 第二个参数的内存大小
	返回值:连接成功返回 0,连接失败返回 - 1
// 接收数据
//如果连接没有断开,接收端接收不到数据,接收数据的函数会阻塞等待数据到达,数据到达后函数解除阻塞,开始接收数据;
//当发送端断开连接,接收端无法接收到任何数据,但是这时候就不会阻塞了,函数直接返回0。
ssize_t read(int sockfd, void *buf, size_t size);
ssize_t recv(int sockfd, void *buf, size_t size, int flags);
	sockfd: 用于通信的文件描述符,accept () 函数的返回值
	buf: 指向一块有效内存,用于存储接收是数据
	size: 参数 buf 指向的内存的容量
	flags: 特殊的属性,一般不使用,指定为 0
	返回值:大于 0:实际接收的字节数;等于 0:对方断开了连接;-1:接收数据失败了
// 发送数据的函数
ssize_t write(int fd, const void *buf, size_t len);
ssize_t send(int fd, const void *buf, size_t len, int flags);
	fd: 通信的文件描述符,accept () 函数的返回值
	buf: 传入参数,要发送的字符串
	len: 要发送的字符串的长度
	flags: 特殊的属性,一般不使用,指定为 0
	返回值:大于 0:实际发送的字节数,和参数 len 是相等的;-1:发送数据失败了

文件描述符对应的内存结构:
一个文件文件描述符对应两块内存, 一块内存是读缓冲区, 一块内存是写缓冲区
  读数据: 通过文件描述符将内存中的数据读出, 这块内存称之为读缓冲区
  写数据: 通过文件描述符将数据写入到某块内存中, 这块内存称之为写缓冲区

监听的文件描述符:
 客户端的连接请求会发送到服务器端监听的文件描述符的读缓冲区中
 读缓冲区中有数据,说明有新的客户端连接
 调用 accept () 函数,这个函数会检测监听文件描述符的读缓冲区
检测不到数据,该函数阻塞
 如果检测到数据,解除阻塞,新的连接建立
通信的文件描述符:
 客户端和服务器端都有通信的文件描述符
 发送数据:调用函数 write () /send (),数据进入到内核中
 数据并没有被发送出去,而是将数据写入到了通信的文件描述符对应的写缓冲区中
内核检测到通信的文件描述符写缓冲区中有数据,内核会将数据发送到网络中

 接收数据:调用的函数 read () /recv (), 从内核读数据
 数据如何进入到内核程序猿不需要处理,数据进入到通信的文件描述符的读缓冲区中
 数据进入到内核,必须使用通信的文件描述符,将数据从读缓冲区中读出即可

读操作:由外界向中心输入,cin / scanf
写操作:由中心向外界输出,cout / printf

在TCP的服务器端,有两类文件描述符:
监听的文件描述符:
  只需要有一个,不负责和客户端通信,负责检测客户端的连接请求,检测到之后调用 accept 就可以建立新的连接
通信的文件描述符:
  负责和建立连接的客户端通信,如果有 N 个客户端和服务器建立了新的连接,通信的文件描述符就有 N 个,每个客 户端和服务器都对应一个通信的文件描述符

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值