Linux中的read/write和recv/send的区别,并使用recv/send实现简单的聊天功能

news2024/10/6 20:37:37

Linux中的read/write和recv/send的区别

r e a d / w r i t e read/write read/write的用法

在 Linux 中,read() 和 write() 是用于在文件描述符上进行数据读写的函数。它们的用法如下:

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

ssize_t write(int fd, const void *buf, size_t count);

其中, f d fd fd 是一个已经打开的文件描述符;
b u f buf buf 是一个指向读或写数据的缓冲区指针;
c o u n t count count 是缓冲区的长度。

r e a d ( ) read() read() 函数用于从文件描述符中读取数据,它会阻塞程序直到读取到数据或发生错误。它返回读取到的字节数,如果返回值为 0 0 0,则表示已经到达文件末尾。如果返回值为 − 1 -1 1,则表示出现了错误,可以通过 e r r n o errno errno 变量来获取错误码。

w r i t e ( ) write() write() 函数用于向文件描述符中写入数据,它会阻塞程序直到所有数据都被写入完毕或发生错误。它返回写入的字节数,如果返回值小于指定的长度,则表示出现了错误。可以通过 e r r n o errno errno 变量来获取错误码。

需要注意的是, r e a d ( ) read() read() w r i t e ( ) write() write() 是基于字节流的,它们不会保留消息的边界信息。如果需要保留消息的边界信息,可以使用 r e a d ( ) read() read() w r i t e ( ) write() write() 函数。

r e c v / s e n d recv/send recv/send的用法

L i n u x Linux Linux 中, r e c v ( ) 和 s e n d ( ) recv() 和 send() recv()send() 是用于在网络套接字上进行数据收发的函数。它们的用法如下:

#include <sys/socket.h>

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

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

其中, s o c k f d sockfd sockfd 是一个已经创建好的、打开的套接字文件描述符;
b u f buf buf 是一个指向接收或发送数据的缓冲区指针;
l e n len len 是缓冲区的长度;
f l a g s flags flags 是一组标志参数,它们控制着函数的行为。

r e c v ( ) recv() recv() 函数用于从套接字中接收数据,它会阻塞程序直到接收到数据或发生错误。它返回接收到的字节数,如果返回值为 0 0 0,则表示连接已经关闭。如果返回值为 − 1 -1 1,则表示出现了错误,可以通过 e r r n o errno errno 变量来获取错误码。 r e c v ( ) recv() recv() 函数的常用标志参数有:

  • MSG_WAITALL:阻塞等待直到接收到指定长度的数据。
  • MSG_PEEK:接收数据但不从接收缓冲区中删除数据。
  • MSG_OOB:接收带外数据。

s e n d ( ) send() send() 函数用于向套接字中发送数据,它会阻塞程序直到所有数据都被发送完毕或发生错误。它返回发送的字节数,如果返回值小于指定的长度,则表示出现了错误。可以通过 e r r n o errno errno 变量来获取错误码。 s e n d ( ) send() send() 函数的常用标志参数有:

  • MSG_DONTWAIT:非阻塞发送数据。
  • MSG_MORE:告诉内核还有更多数据需要发送。
  • MSG_NOSIGNAL:在发送数据时忽略 SIGPIPE 信号。

L i n u x Linux Linux中的 r e a d / w r i t e read/write read/write r e c v / s e n d recv/send recv/send的区别

L i n u x Linux Linux中, r e a d / w r i t e read/write read/write r e c v / s e n d recv/send recv/send是用于从 文件描述符 文件描述符 文件描述符 套接字 套接字 套接字进行数据读写的系统调用。它们之间的主要区别如下:

  1. 参数不同
    r e a d / w r i t e read/write read/write的参数是 文件描述符、缓冲区和读 / 写字节数 文件描述符、缓冲区和读/写字节数 文件描述符、缓冲区和读/写字节数
    r e c v / s e n d recv/send recv/send的参数是 套接字、缓冲区和读 / 写字节数 套接字、缓冲区和读/写字节数 套接字、缓冲区和读/写字节数

  2. 返回值不同
    r e a d / w r i t e read/write read/write的返回值为已读/写字节数,如果遇到错误则返回-1。
    r e c v / s e n d recv/send recv/send的返回值为已接收/发送字节数,如果遇到错误则返回-1。

  3. 应用场景不同
    r e a d / w r i t e read/write read/write通常用于 读写普通的文件、管道等 读写普通的文件、管道等 读写普通的文件、管道等
    r e c v / s e n d recv/send recv/send则用于 网络编程中的套接字通信 网络编程中的套接字通信 网络编程中的套接字通信

  4. 处理方式不同
    r e a d / w r i t e read/write read/write在读写时使用文件偏移量来确定从哪里读取或写入数据,并根据需要更新该偏移量。
    r e c v / s e n d recv/send recv/send则没有类似的偏移量概念,它们一次性读取或发送指定数量的数据。

总体而言, r e a d / w r i t e read/write read/write适合用于本地文件和管道等,而 r e c v / s e n d recv/send recv/send适合用于网络通信中的套接字。

下面是一个使用read/write进行文件读写操作的例子:

该程序打开一个名为 t e s t . t x t test.txt test.txt的文件,并使用 r e a d read read将其内容读取到缓冲区中,然后使用 w r i t e write write将内容写入标准输出。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

int main() {
    int fd = open("test.txt", O_RDWR);
    if (fd == -1) {
        printf("Failed to open file\n");
        exit(1);
    }
    
    char buffer[1024];
    int num_read = read(fd, buffer, sizeof(buffer));
    if (num_read == -1) {
        printf("Failed to read file\n");
        exit(1);
    }
    
    int num_written = write(STDOUT_FILENO, buffer, num_read);
    if (num_written == -1) {
        printf("Failed to write file\n");
        exit(1);
    }

    close(fd);
    return 0;
}

下面是一个使用recv/send进行网络通信的例子:

下面是一个使用recv/send进行网络通信的服务器与客户端互发消息的例子:

// Server
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define PORT 8081

int main()
{
    int server_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock == -1)
    {
        printf("Failed to create socket\n");
        exit(1);
    }

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
    {
        printf("Failed to bind\n");
        exit(1);
    }

    if (listen(server_sock, 5) == -1)
    {
        printf("Failed to listen\n");
        exit(1);
    }

    printf("Server is listening on port %d...\n", PORT);

    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_len);
    if (client_sock == -1)
    {
        printf("Failed to accept connection\n");
        exit(1);
    }

    char buffer[1024];
    while (1)
    {

        memset(buffer, 0, sizeof buffer);                                // 收之前先把缓存区清空
        int num_received = recv(client_sock, buffer, sizeof(buffer), 0); /收///
        if (num_received == -1)
        {
            printf("Failed to receive message\n");
            exit(1);
        }
        else if (num_received == 0)
        {
            break; // Client closed connection
        }

        printf("Received message: %s", buffer);

        const char *message = "Hello, client!\n";
        int num_sent = send(client_sock, message, strlen(message), 0); ///发
        if (num_sent == -1)
        {
            printf("Failed to send message\n");
            exit(1);
        }
    }

    close(client_sock);
    close(server_sock);
    return 0;
}

该程序创建了一个服务器套接字,绑定到指定端口,并使用listen开始监听。当客户端连接时,使用accept接受连接并进行通信。在接受到客户端发送的消息后,服务器会将其打印出来,并向客户端发送一条回复。

// Client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define PORT 8081

int main()
{
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        printf("Failed to create socket\n");
        exit(1);
    }

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
    {
        printf("Failed to connect\n");
        exit(1);
    }

    char buffer[1024];
    while (1)
    {
        printf("Enter message: ");
        fgets(buffer, sizeof(buffer), stdin);

        int num_sent = send(sock, buffer, strlen(buffer), 0); /发/
        if (num_sent == -1)
        {
            printf("Failed to send message\n");
            exit(1);
        }
        else if (num_sent == 0)
        {
            break; // Server closed connection
        }

        memset(buffer, 0, sizeof buffer);                         // 收之前先把缓存区清空
        int num_received = recv(sock, buffer, sizeof(buffer), 0); /收//
        if (num_received == -1)
        {
            printf("Failed to receive message\n");
            exit(1);
        }
        else if (num_received == 0)
        {
            break; // Server closed connection
        }

        printf("Received message: %s", buffer);
    }

    close(sock);
    return 0;
}

该程序创建了一个客户端套接字,连接到服务器。在输入一条消息后,使用send向服务器发送该消息,并收到服务器的回复。当检测到服务器关闭连接时,程序退出。

这两个程序可以相互通信,实现简单的聊天功能。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云原生】Kubernetes(k8s)部署 MySQL+Dubbo+Nacos服务

一、说明二、部署 MySQL三、部署 Nacos四、部署 Dubbo 服务4.1. 创建镜像仓库的密钥4.2. 部署 provider 服务4.3. 部署 consumer 服务五、测试一、说明 本文介绍基于 Kubernetes(k8s) 环境集成阿里云 私有镜像仓库 来部署一套 Dubbo Nacos 的微服务系统&#xff0c;并使用 Ku…

VUE前端项目环境搭建

背景&#xff1a; 想要使用vue搭建一个前端项目&#xff0c;写个小网站练练手&#xff0c;因为没有前端经验&#xff0c;所以从网上找了一个vue得开源模板使用&#xff0c;经过一番挑选选中了字节公司花裤衩大佬开源得项目&#xff0c;地址如下&#xff1a; 开源项目地址&…

第三代api自动化测试框架使用教程(pytest+allure+sql+yaml)

使用教程一、配置1、环境配置2、框架配置3、启动入口二、用例编写1、用例模板2、参数依赖写法2、函数&#xff08;方法插件&#xff09;写法3、接口上传文件和表单参数4、接口上传json参数5、接口无数据填写6、code断言7、body断言7、json断言8、sql断言9、完整断言写法&#x…

三种不同实现ublk的零拷贝I/O的方法

用户态块设备ublk&#xff0c;就是提供/dev/ublkbX这样的标准块设备给业务&#xff0c;业务读写这个块的实际IO处理由编写的用户态的代码决定。这就好比使用FUSE&#xff0c;所有对挂载于FUSE的目录的读写都是编写的IO handler来处理一样。使用用户态块设备&#xff0c;可以方便…

产品经理必读|用户研究方法总结①

众所周知&#xff0c;理解用户需求&#xff0c;识别用户痛点&#xff0c;是产品或功能成型之前绕不开的过程。而要获取到用户真实的需求和痛点&#xff0c;唯一的方法就是做用户调研。而用研的方法都有哪些呢&#xff1f;今天我就来给大家分享一下行业中常见的用研方法。 用研的…

ESP32设备驱动-VL53L0X飞行时间(激光测距)传感器驱动

VL53L0X飞行时间(激光测距)传感器驱动 文章目录 VL53L0X飞行时间(激光测距)传感器驱动1、VL53L0X介绍2、硬件准备3、软件准备4、驱动实现1、VL53L0X介绍 VL53L0X 是新一代飞行时间 (ToF) 激光测距模块,采用当今市场上最小的封装,与传统技术不同,无论目标反射率如何,都能提…

项目中开发固定表头和首列的表格【付代码】

前言 前段时间做移动端的项目&#xff0c;项目中需要一个固定表头和首列的表格&#xff0c;但由于是移动端的&#xff0c;组件库里没有类似的&#xff0c;于是&#xff0c;就去网上找看有没有类似的&#xff0c;结果越找越气&#xff0c;10个文章9个抄&#xff0c;抄也行&#…

安全狗入选网络安全行业全景图(第十版)多个细分领域

4月7日&#xff0c;安全牛正式发布第十版网络安全行业全景图。 作为国内云原生安全领导厂商&#xff0c;安全狗也凭借综合的安全能力脱颖而出入选全景图多个领域。 据悉&#xff0c;全景图报告调研基于企业自主申报&#xff0c;并对申报企业收录有严格要求&#xff0c;安全牛…

Zookeeper集群+Kafka集群

目录 一、Zookeeper Zookeeper 概述 定义 工作机制 Zookeeper特点 Zookeeper数据结构 ZooKeeper应用场景 统一命名服务 统一配置管理 统一集群管理 服务器动态上下线 软负载均衡 第一次启动选举机制 非第一次启动选举机制 二、部署Zookeeper集群 1、实验准备 2…

第60章 用户增、修、删的前端实现

1 \src\components\Users\AddUser.vue <template> <!-- elmentUI 子页面的渲染显示注意事项说明&#xff1a; 子页面的渲染显示必须的使用“<el-dialog></el-dialog>标签及其所包含的子标签&#xff0c;否则子页面将不会被渲染显示出来。” --> <…

Python学习笔记--判断语句

&#xff08;一&#xff09; 布尔类型和比较运算符 1. 布尔类型&#xff1a;判断结果 True&#xff1a;表示真&#xff08;是、肯定&#xff09; False&#xff1a;表示假&#xff08;否、否定&#xff09; """ 演示布尔类型的定义 以及比较运算符的应用 "…

BCM系统组成及控制原理

1 输入控制 由于负载能力、抗干扰能力等客观情况。许多信号量无法直接施加至MCU之上&#xff0c;须有适当的输入电路(Input circuit)将信号进行隔离、调理&#xff0c;方可安全可靠地传递给MCU。 下面以开关信号和脉冲信号2种来分述。 1)开关信号的输入。 即将系统与电源正…

高频算法:Leetcode53 最大子数组和

今天讲的是Leetcode第53题&#xff0c;最大子数组和 首先观察题目&#xff0c;题目需要我们找出具有最大和的连续子数组&#xff0c;直接拿题目中的示例来做一个演示&#xff0c;找一找什么规律下的连续子数组才能得到最大的和 先从-2开始&#xff0c;-2 1 -1 此时我们的和…

【Python】Python读写.xlsx文件(基本操作、空值补全等)

【Python】Python读写.xlsx文件&#xff08;Pandas&#xff09; 文章目录【Python】Python读写.xlsx文件&#xff08;Pandas&#xff09;1. 介绍2. Pandas读写xlsx文件2.1 基本操作2.1.1 实现任务2.1.2 代码2.1.3 结果2.2 进阶操作2.2.1 写操作2.2.2 查看数据表的基本信息2.2.2…

集中一个主题,密集学习几个月,突飞猛进

集中一个主题&#xff0c;密集学习几个月大长进 诺贝尔奖获得者西蒙发现 密集学习了几个月品牌营销的知识 长进明显 原来是有科学规律的 趣讲大白话&#xff1a;大力出奇迹 【趣讲信息科技132期】 **************************** 西蒙学习法&#xff1a;“对于一个有一定基础的人…

KANO模型-产品需求调研利器

最近要做一个项目&#xff0c;需要调研客户的真实需求&#xff0c;我们有一些可提供的功能&#xff0c;需要通过问卷调研出客户对功能的优先级需求。但问卷调研的结果能反映客户的真实需求和痛点吗&#xff1f;如何给这些需求排优先级&#xff0c;以及所占的权重&#xff1f;如…

【python】只需一段代码,剪辑一个视频——Moviepy详解

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、准备二、视频剪辑三、视频拼接四、逐帧变化四、导出GIF总结前言 知道吗&#xff0c;用moviepy一行代码就能够快速剪辑视频中某个区间的片段&#xff1a; cl…

mac m1系统安装安卓手机模拟器

背景&#xff1a;本人是一名开发人员&#xff0c;本地小程序上的需要地图导航到手机上&#xff0c;所以找到一个mac&#xff08;m1&#xff09;安装安卓模拟器的方案&#xff0c;这里记录分享一下。 废话不多说直接上步骤&#xff0c;很详细跟着步骤走就能完成&#xff01;&am…

【MySQL】delete和truncate的用法和区别

一、delete和truncate的用法 有如下数据表t_student 关键字delete和truncate都用来清除表中数据&#xff0c;语法结构为&#xff1a; delete from t_student;truncate table t_student; 两条SQL操作后的结果一样&#xff1a;删除了表中数据&#xff0c;但是会保留表的结构&a…

OpenAI Embedding:快速实现聊天机器人(一)

theme: orange 本文正在参加「金石计划」 上文 OpenAI Embedding&#xff1a;基于人工智能的搜索新篇章 有讲到Embedding的基础概念以及OpenAI Embedding 的能力和应用场景&#xff0c;这篇文章讲讲如何手把手构建聊天机器人。 聊天机器人介绍 聊天机器人作为一项重要的企业级服…