网络(3)TCP通信

这几天学习了TCP通信。它和UDP通信是网络通信的重点。

TCP是面向连接的协议,正式收发数据之前,要通过三次握手建立连接,通信结束使用四次挥手断开连接。

三次握手

  1. 客户端(主动发起连接)发送SYN报文
  2. 服务器返回 ACK+SYN
  3. 客户端回复ACK,连接建立完成。

四次挥手

用来结束TCP连接,保证数据完整传输。

如果双方没有待传输数据,四次挥手也会简化成三次挥手。

主动关闭端发送FIN

被动关闭端回复ACK;如果数据全部发送完毕,会继续发送ACK+FIN

被动关闭端再发送FIN

主动关闭端回复ACK

TCP依靠序号、确认序号保证数据完整可靠传输。

序号:代表当前数据包起始字节编号

确认序号:接收方告诉发送方,下一次希望收到的字节编号

还有滑动窗口做流量控制,拥塞控制应对网络拥堵,掉线检测机制维护连接状态。

TCP粘包问题

TCP是流式协议,没有消息边界。连续发送多份数据,接收端有可能把多条数据包粘在一起收到。

常见解决办法:

  1. 发送之间增加延时
  2. 设置消息边界,比如用\r\n做分隔符
  3. 使用定长发送

TCP报文头部

TCP头部固定20字节。里面有多个标志位:

SYN:请求建立连接

ACK:确认应答

FIN:结束通信

RST:重置连接

PSH:推送数据

URG:紧急数据

ACK标志置1的时候,32位确认序号才会生效。

TCP socket核心函数

客户端函数

  1. socket() 创建套接字

    int tcpsocket = socket(AF_INET, SOCK_STREAM, 0);

    AF_INET代表IPv4,SOCK_STREAM代表TCP流套接字。

  2. connect():客户端主动发起连接

    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    sockfd:socket文件描述符

    addr:目标服务器地址

    addrlen:地址结构体长度

    返回0成功,‑1失败。

  3. send():向套接字发送数据

    ssize_t send(int sockfd, const void *buf, size_t len, int flags);

    buf:发送缓冲区首地址;len:发送长度;flags一般填0

    返回:成功返回发送字节数;失败返回‑1。

  4. recv():从套接字接收数据

    ssize_t recv(int sockfd, void *buf, size_t len, int flags);

    buf:接收缓冲区;len:最大接收字节;flags默认0

    返回:成功返回收到字节;失败‑1;返回0代表对方关闭连接。

服务器端函数

  1. listen():开启监听,等待客户端连接请求

    int listen(int sockfd, int backlog);

    backlog:内核中未处理连接请求队列的最大个数。成功返回0,失败‑1。

  2. accept():取出监听队列第一个客户端连接

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    sockfd:监听socket

    addr:保存客户端地址信息

    addrlen:传入地址结构体大小,调用后输出实际地址长度

    返回值:返回新的文件描述符,后续和客户端通信就使用这个新fd。

TCP与UDP对比

TCP UDP

连接 面向连接 无连接

可靠性 可靠安全 不可靠

资源开销 开销大 开销小

实现逻辑 复杂 简单

UDP不用建立连接,速度快,但是会丢包,不保证顺序。

小结

  1. TCP要先三次握手建连接,结束四次挥手;存在粘包,要自己处理消息边界。
  2. 客户端:socket → connect → send/recv
  3. 服务器:socket → listen → accept → send/recv
  4. recv返回0代表对端断开,这点写代码一定要留意。
相关推荐
μθημα1 小时前
Kubernetes 微服务网络实践:Service 与 Ingress 从入门到灰度发布
网络·微服务·kubernetes
晊晌_h1 小时前
嵌入式从0到精通——Linux 网络通信|TCP、HTTP 网络编程
linux·c语言·网络
MetaLite1 小时前
HTTPS之外的响应加密-GCM序列化与处理器顺序
网络协议·http·https
姚不倒1 小时前
Tengine 实战:主动健康检查 + 动态 Upstream 配置
运维·网络·nginx
茶栀(*´I`*)1 小时前
Python网络机器人入门:从Robots协议、网页结构到Requests库的基础实践
网络·python·机器人
Ai思想家2 小时前
一次模型调用会留下什么:聚合平台的日志留存与数据边界
大数据·服务器·网络·人工智能
筝筝ba2 小时前
linux查询某个网卡是否插了对应网线的命令
linux·运维·网络
姚不倒2 小时前
HAProxy 系列(二):健康检查与 SSL 卸载 — 保障可用性与性能
运维·网络·网络协议·ssl·haproxy
ue星空2 小时前
登录失败:failed to start login server: 以一种访问权限不允许的方式做了一个访问套接字的尝试。 (os error 10013)
网络·codex