TCP 编程探秘:建立连接、数据传输与多路复用的精髓

这篇具有很好参考价值的文章主要介绍了TCP 编程探秘:建立连接、数据传输与多路复用的精髓。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

0. TCP 编程函数概览

函数名 用法 参数 返回值 说明
socket int socket(int domain, int type, int protocol); domain: 协议族
type: 套接字类型
protocol: 协议类型
成功时返回套接字描述符,失败时返回 -1 创建一个套接字
bind int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockfd: 套接字描述符
addr: 指向地址结构的指针
addrlen: 地址结构的长度
成功时返回 0,失败时返回 -1 将套接字与特定地址和端口绑定
listen int listen(int sockfd, int backlog); sockfd: 套接字描述符
backlog: 等待连接队列的最大长度
成功时返回 0,失败时返回 -1 将套接字设置为监听状态
accept int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); sockfd: 套接字描述符
addr: 指向用于存放客户端地址的缓冲区
addrlen: 地址结构的长度
成功时返回新的套接字描述符,失败时返回 -1 接受客户端的连接请求
connect int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockfd: 套接字描述符
addr: 指向服务器地址的指针
addrlen: 地址结构的长度
成功时返回 0,失败时返回 -1 发起与服务器的连接请求
send ssize_t send(int sockfd, const void *buf, size_t len, int flags); sockfd: 套接字描述符
buf: 指向要发送数据的缓冲区
len: 要发送的数据长度
flags: 发送标志
成功时返回发送的字节数,失败时返回 -1 发送数据
recv ssize_t recv(int sockfd, void *buf, size_t len, int flags); sockfd: 套接字描述符
buf: 用于存放接收数据的缓冲区
len: 缓冲区的长度
flags: 接收标志
成功时返回接收的字节数,失败时返回 -1 接收数据
close int close(int sockfd); sockfd: 套接字描述符 成功时返回 0,失败时返回 -1 关闭套接字

0.1. 错误处理相关函数

函数名 用法 参数 返回值 说明
perror void perror(const char *s); s: 用于输出错误信息的字符串 无返回值 输出描述性错误消息
errno int errno; 无参数 整数值 全局变量,存储发生错误的代码
strerror char *strerror(int errnum); errnum: 错误码 返回错误描述字符串 根据错误码返回描述性字符串

I. 建立TCP连接

A. TCP简介

  • TCP传输控制协议概述

    • TCP是一种面向连接的、可靠的传输层协议,用于在网络中提供可靠的数据传输服务。
    • 它通过各种机制(如序列号、确认应答、重传)确保数据的完整性和可靠性。
  • 可靠、面向连接通信的重要性

    • 可靠性:TCP通过序列号、确认和重传等机制,保证数据在传输过程中不丢失、不重复,并按顺序交付。
    • 面向连接:建立连接的过程中,通信双方会进行协商,确保彼此能够正常通信,并在通信结束后释放连接,释放资源。

B. 三次握手

  • 三次握手的解释:SYN、SYN-ACK、ACK

    握手阶段 发送方 接收方 描述
    1. 发送SYN Client Server 发起连接请求,同步序列号(SYN)
    2. 接收SYN Server Client 收到请求,回复同步确认和自己的SYN(SYN-ACK)
    3. 发送ACK Client Server 确认接收方的SYN,完成握手(ACK)
  • 序列号在建立可靠连接中的重要性

    • 每个TCP报文段都包含一个序列号,用于标识发送的数据在整个数据流中的位置。序列号的使用使得接收方能够正确地组装数据流,并实现可靠的数据传输。
  • 通过示例代码演示三次握手过程

    • 下面是一个简单的C语言示例代码,演示了TCP三次握手的过程:
    // Client
    send_syn();        // 发送SYN
    recv_syn_ack();    // 接收SYN-ACK
    send_ack();        // 发送ACK
    
    // Server
    recv_syn();        // 接收SYN
    send_syn_ack();    // 发送SYN-ACK
    recv_ack();        // 接收ACK
    

II. 数据传输

A. TCP数据传输方式

  • 数据流的概念

    • TCP提供的是一个面向字节流的数据传输方式,数据被看作是无边界的字节流,而不是分段的消息。
    • 这意味着发送方的数据可以被接收方按照任意大小的块进行接收。
  • 使用send()recv()等相关函数进行数据传输

    • send(socket, buffer, size, flags):将数据从缓冲区发送到连接的套接字。
    • recv(socket, buffer, size, flags):从连接的套接字接收数据并存储到缓冲区。
  • 处理粘包和拆包问题

    • 粘包(Packet Pawning):多个发送的小数据包被接收方当作一个大数据包处理。
    • 拆包(Packet Splitting):一个发送的大数据包被接收方分割成多个小数据包处理。
    • 解决方案包括消息边界标记、固定长度消息和长度字段等方法。

III. 多路复用

A. 多路复用机制介绍

  • select()poll()epoll()等多路复用机制概述

    • 多路复用允许单个进程处理多个连接,提高系统的并发性能。
    • select():基于轮询的机制,效率较低。
    • poll():改进的select(),支持更多的文件描述符,但仍有限。
    • epoll():Linux特有的高性能多路复用机制,支持水平触发和边缘触发。
  • 多路复用的优势和适用场景

    • 通过单一的系统调用来监视多个文件描述符,提高效率。
    • 适用于大量的并发连接,如服务器需要同时处理多个客户端请求。
  • 通过代码示例演示多路复用的基本用法

    • 示例代码(使用epoll()):
    // 创建epoll实例
    int epoll_fd = epoll_create1(0);
    
    // 将套接字添加到epoll监视列表
    struct epoll_event event; 
    event.events = EPOLLIN;
    event.data.fd = server_socket;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_socket, &event);
    
    while (1) {
        struct epoll_event events[MAX_EVENTS];
        int ready_fds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
    
        for (int i = 0; i < ready_fds; ++i) {
            if (events[i].data.fd == server_socket) {
                // 处理新的客户端连接
                // ...
            } else {
                // 处理已连接客户端的数据
                // ...
            }
        }
    }
    

B. select()函数详解

  • select()函数的使用方法和参数

    • select(max_fd + 1, &read_fds, &write_fds, &except_fds, &timeout):监视文件描述符的可读、可写和异常情况。
  • 阻塞和非阻塞模式的区别

    • 阻塞模式:调用select()后,会一直等待直到有文件描述符就绪。
    • 非阻塞模式:通过设置非阻塞标志,select()调用会立即返回,无论文件描述符是否就绪。
  • 错误处理和超时设置

    • 返回值小于0表示发生错误,可以通过errno获取错误信息。
    • 超时设置通过timeout参数实现,允许程序定时检查文件描述符的状态。

C. poll()函数详解

  • poll()函数的使用方法和参数

    • poll(struct pollfd fds[], nfds, timeout):监视一组文件描述符的可读、可写和异常情况。
  • select()的比较优势

    • poll()没有文件描述符数的限制,更适用于大规模的并发连接。
  • 处理大量文件描述符的效率

    • 采用数组结构,通过revents字段判断文件描述符的状态,效率相对较高。

D. epoll()函数详解

  • epoll()函数的使用方法和参数

    • epoll_create1(flags):创建一个epoll实例,epoll_ctl()用于添加、修改和删除文件描述符,epoll_wait()等待文件描述符就绪。
  • 边缘触发和水平触发模式的区别

    • 边缘触发:只在状态变化时通知一次,需要使用非阻塞模式处理文件描述符。
    • 水平触发:在状态保持的情况下会持续通知。
  • 高效处理大量并发连接的方法

    • 通过事件驱动的方式,只关注活跃的文件描述符,避免遍历整个文件描述符集合。
    • 使用EPOLLET标志开启边缘触发模式,提高效率。

IV. 实际应用案例

A. 开发一个简单的TCP服务器和客户端

1. TCP服务器
  • 服务器端伪代码

    // 创建服务器套接字
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);          
    
    // 绑定服务器地址
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = INADDR_ANY;
    server_address.sin_port = htons(PORT);
    bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address));
    
    // 监听连接请求
    listen(server_socket, BACKLOG);
    
    // 接受客户端连接
    int client_socket = accept(server_socket, NULL, NULL);
    
    // 接收和处理客户端数据
    char buffer[BUFFER_SIZE];
    recv(client_socket, buffer, BUFFER_SIZE, 0);
    
    // 发送数据给客户端
    send(client_socket, "Hello, client!", strlen("Hello, client!"), 0);
    
    // 关闭连接
    close(client_socket);
    close(server_socket);
    
  • 服务器端流程图

2. TCP客户端
  • 客户端伪代码

    // 创建客户端套接字
    int client_socket = socket(AF_INET, SOCK_STREAM, 0);             
    
    // 设置服务器地址
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = inet_addr(SERVER_IP);
    server_address.sin_port = htons(PORT);
    
    // 连接到服务器
    connect(client_socket, (struct sockaddr*)&server_address, sizeof(server_address));
    
    // 发送数据给服务器
    send(client_socket, "Hello, server!", strlen("Hello, server!"), 0);
    
    // 接收服务器响应
    char buffer[BUFFER_SIZE];
    recv(client_socket, buffer, BUFFER_SIZE, 0);
    
    // 处理服务器响应
    printf("Server response: %s\n", buffer);
    
    // 关闭连接
    close(client_socket);
    
  • 客户端流程图

3. 处理连接、数据传输和关闭连接的过程
  • 连接过程

    • 服务器通过socket()bind()listen()创建并准备监听套接字。
    • 客户端通过socket()connect()创建并连接到服务器。
  • 建立连接流程图

  • 数据传输过程

    • 服务器通过accept()接受客户端连接,并使用send()recv()进行数据传输。
    • 客户端通过send()recv()与服务器进行数据交互。
  • 关闭连接过程

    • 服务器和客户端均通过close()关闭套接字,释放相关资源。

这个案例演示了一个简单的TCP服务器和客户端的实现过程,使用了伪代码、流程图和文字描述,以便更好地理解连接、数据传输和关闭连接的整个过程。文章来源地址https://www.toymoban.com/news/detail-772332.html

到了这里,关于TCP 编程探秘:建立连接、数据传输与多路复用的精髓的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Ai-WB2模组与手机建立基于Gatt的连接,实现在UART-Bluetooth LE透传模式下传输数据

    安信可官网的combo_AT固件不断更新,为了方便大家开发WB2系列,本示例使用安信可自主开发的AT固件实现蓝牙与串口透传通讯。波特率115200。 硬件 软件 Ai-WB2系列模组或开发板 Combo-AT_V4.18版本固件 Type-C数据线 nRF Connect(蓝牙调试工具) 输入以下 AT指令 。 记住如下信息 (1) 手机

    2024年02月12日
    浏览(26)
  • STM32_ADC————ADC+DMA多路数据传输,看门狗中断,传感器控制LED

    一:介绍ADC与DMA的基本情况与初始化 二:利用ADC+DMA+看门狗中断+传感器控制LED灯代码 三:总结实验过程中碰到的错误与问题 通过DMA转运ADC的数据,设置ADC的中断看门狗阈值,当光敏传感器的ADC采样值在看门狗高低阈值中间,不触发中断,如果超过看门狗的高低阈值就会触发

    2024年02月04日
    浏览(35)
  • TCP可靠数据传输

    TCP的可靠数据传输 1.TCP保证可靠数据传输的方法 TCP主要提供了检验和、序号/确认号、超时重传、最大报文段长度、流量控制等方法实现了可靠数据传输。 检验和 通过检验和的方式,接收端可以检测出来数据是否有差错和异常,假如有差错就会直接丢失该TCP报文段。 序号/确

    2024年02月11日
    浏览(26)
  • TCP数据传输协议详解

    1、TCP概述 1、点对点 一个发送方,一个接收方 2、可靠地,按顺序的字节流 没有报文边界 3、管道化(流水线) TCP拥塞控制和流量控制设置 窗口大小 4、发送和接收缓存 5、全双工数据 在同一连接中数据流双向流动 MSS:最大报文段大小 6、面向连接: 在数据交换之前,通过握

    2024年02月13日
    浏览(40)
  • TCP传输数据

    2024年01月23日
    浏览(19)
  • TCP_可靠数据传输原理

    在网络通信中,TCP是确保数据可靠传输的关键协议。但在我们深入研究TCP拥塞控制技术之前,让我们先探索可靠数据传输的原理,特别是TCP头部中一些重要字段的作用。 网络层提供了点对点的通信服务,努力交付数据报,但并不保证可靠交付。这引出了运输层的角色,而TC

    2024年01月20日
    浏览(33)
  • 数据通信——传输层TCP(可靠传输原理的ARQ)

    上一篇讲述了停止等待协议的工作流程,在最后提到了ARQ自动请求重传机制。接下来,我们就接着上一篇的篇幅,讲一下ARQ这个机制 还是这个图来镇楼  发送端对出错的数据帧进行重传是自动进行的,因而这种差错控制体制常简称为ARQ(Automatic Repeat reQuest),直译是自动重传请

    2024年02月10日
    浏览(31)
  • TCP是如何传输数据的?

    做IT相关的工作,肯定都离不开网络,网络中最重要的协议是TCP。无论是实际工作还是笔试面试,你看哪里能少得了TCP?我考过RFC中与TCP相关的文档,也看过Linux中与TCP相关的源码,也看过不少框架中的TCP相关的代码,对TCP是有点感觉了。 一直想找个时间来分享下TCP相关的知

    2024年02月08日
    浏览(27)
  • 实验:验证TCP套接字传输的数据不存在数据边界

    来源: 《TCP/IP网络编程》 学习ing 自己动手,把坑踩一遍,也可以学习到很多。 Linux环境下: 客户端: 服务端程序不变。 结果:    

    2024年02月12日
    浏览(27)
  • QT下TCP协议实现数据网络传输

    QT开发框架以其跨平台的优势,在全世界IT界如雷贯耳。其封装了功能齐全的各种类,大大的提高了开发者的效率。本篇内容将介绍如何使用QT 6.4.1框架开发服务器和客户端程序,让两端能够首发消息,服务端往客户端发送文件(客户端往服务器发送类似,没有实现)。  说明

    2023年04月08日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包