网络(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代表对端断开,这点写代码一定要留意。
相关推荐
花间相见9 小时前
【计算基础|网络14】网络层:IP、ICMP 与 ping
网络·网络协议·tcp/ip
OnlineProxy9 小时前
为 LangChain 和 CrewAI 构建自定义工具:将代理 IP 轮换封装至智能体函数中
网络协议·tcp/ip·langchain
半杯咖啡半行码11 小时前
Linux 驱动开发入门:内核模块编程基础
linux·服务器·网络
智能直播11 小时前
RK3528 V4L2 框架 UVC 接口自动获取 H.264 / MJPEG / YUYV 格式:从内核采集到硬解分发
java·网络·实时音视频·视频编解码·h.264
睿智の男孩12 小时前
MIG IP核对DDR3的输出时序分析记录
网络·网络协议·tcp/ip
艾芯微科技12 小时前
高充放电流锂电充放 SoC:ETA9885E10,便携储能、小移动电源 BOM 选型笔记
网络·单片机·嵌入式硬件·集成测试·51单片机
2401_8685347812 小时前
数据交换方式
服务器·网络
艾芯微科技12 小时前
钰泰 ETA6973PQ3Y|QFN3×3 2A 同步降压 Buck,I2C 可配置多档输出,动态调压 PMIC
网络·单片机·嵌入式硬件·fpga开发·集成测试·51单片机
默|笙12 小时前
【Linux网络】_udp_socket(认识)
linux·网络·udp