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

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.mfbz.cn/a/12233.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Three.js教程:第一个3D场景

推荐&#xff1a;将 NSDT场景编辑器加入你3D工具链 其他工具系列&#xff1a; NSDT简石数字孪生 下面的代码完整展示了通过three.js引擎创建的一个三维场景&#xff0c;在场景中绘制并渲染了一个立方体的效果&#xff0c;为了大家更好的宏观了解three.js引擎&#xff0c; 尽量使…

基于SpringBoot的私人健身和教练的预约管理系统源码数据库论文

目 录 第一章 概述 1.1研究背景 1.2开发意义 1.3研究现状 1.4研究内容 1.5论文结构 第二章 开发技术介绍 2.1系统开发平台 2.2平台开发相关技术 2.2.1 Javar技术 2.2.2 Mysql数据库介绍 2.2.3 Mysql环境配置 2.2.4 B/S架构 2.2.5 Springboot框架 …

设计模式-结构型模式之外观模式

4. 外观模式 4.1. 模式定义 外观模式(Facade Pattern)&#xff1a;外部与一个子系统的通信必须通过一个统一的外观对象进行&#xff0c;为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式定义了一个 高层接口&#xff0c;这个接口使得这一子系统更加容易使用。外观模…

socket 到底是个啥

哈喽大家好&#xff0c;我是咸鱼 我相信大家在面试过程中或多或少都会被问到这样一个问题&#xff1a;你能解释一下什么是 socket 吗 我记得我当初的回答很是浅显&#xff1a;socket 也叫套接字&#xff0c;用来负责不同主机程序之间的网络通信连接&#xff0c;socket 的表现…

使用树状图可视化聚类

一般情况下&#xff0c;我们都是使用散点图进行聚类可视化&#xff0c;但是某些的聚类算法可视化时散点图并不理想&#xff0c;所以在这篇文章中&#xff0c;我们介绍如何使用树状图&#xff08;Dendrograms&#xff09;对我们的聚类结果进行可视化。 树状图 树状图是显示对象…

大模型混战,阿里百度华为谁将成就AI时代的“新地基”?

从算力基础到用户生态&#xff0c;群雄逐鹿大模型 自2022年stable diffusion模型的进步推动AIGC的快速发展后&#xff0c;年底&#xff0c;ChatGPT以“破圈者”的姿态&#xff0c;快速“吸粉”亿万&#xff0c;在全球范围内掀起了一股AI浪潮&#xff0c;也促使了众多海外巨头竞…

微信为什么使用 SQLite 保存聊天记录

SQLite “只是”一个库&#xff0c;它不是传统意义上的服务器。因此&#xff0c;在某些场合下&#xff0c;它确实不合适。但是&#xff0c;在相当多的其他场合&#xff0c;它却是最合适的选择。SQLite 号称是部署和使用最广泛的数据库引擎。我认为这很有可能&#xff0c;因为 S…

10个镜像网站工具箱供你使用,不注册ChatGPT也能免费使用ChatGPT

ChatGPT已经成为了人工智能技术中备受瞩目的一员&#xff0c;它可以为我们带来更加智能化、个性化的交互体验。对于没有ChatGPT账号或者不想注册账号的人来说&#xff0c;他们可能会错过这种神奇的体验。 而本篇文章就帮大家解决这个问题&#xff0c;不用登录ChatGPT账号&…

Doris(9):删除数据(Delete)

Delete不同于其他导入方式&#xff0c;它是一个同步过程。和Insert into相似&#xff0c;所有的Delete操作在Doris中是一个独立的导入作业&#xff0c;一般Delete语句需要指定表和分区以及删除的条件来筛选要删除的数据。 Doris 目前可以通过两种方式删除数据&#xff1a; DE…

使用Schrödinger Python API系列教程 -- 介绍 (一)

使用Schrdinger Python API系列教程 – 介绍 (一) 本文档可从Schrdinger网站www.schrodinger.com/pythonapi访问。 从Python文档字符串生成的完整API文档可以在这里访问 介绍 在最高级别上&#xff0c;Schrdinger Python API提供了一个基本的分子结构类&#xff0c;并允许与…

【JavaEE】关于synchronized总结-Callable用法及JUC的常见问题

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶synchronized原理是什么&#xff1f;synchronized到底有什么特点&#xff0c;synchronized的锁策略是什么&#xff0c;是怎么变化的呢&#xff1f;本篇文章总结出, Synchronized 具有以下特性…

HyperWorks2021软件安装教程

下载软件 https://www.xsoftnet.com/share/a0004MWyQAg9r.html产品介绍&#xff1a; HyperWorks一款功能强大的开放式架构仿真软件。拥有先进的技术以及高性能、高效和创新的产品&#xff0c;为用户提供了设计、仿真和制造等服务。支持电磁分析设计、材料建模制造、多物理场分…

【数据结构】二叉树链式结构

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;初阶数据结构 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对…

18 隐私模式下面发送 http 请求不成功

前言 是这样的一个情况, 最近 我们服务存在这样的一个问题 是在登录界面, 假设我用户名 或者 密码输入错误, 能够得到真确的结果, 拿到了 正常的 http 响应, 回来 "用户名 或者 密码 不正确 " 但是 假设是在 隐私模式下面, 同样的输入, 同样的服务, 但是结果 不一…

【配电网故障重构SOP】基于二阶锥松弛的加光伏风机储能进行的配电网故障处理和重构【考虑最优潮流】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Java多线程基础学习(一)

1. 创建线程 1.1 通过构造函数&#xff1a;public Thread(Runnable target, String name){} 或&#xff1a;public Thread(Runnable target){} 示例: Thread thread1 new Thread(new MyThread(), "mythread"); class MyThread extends Thread(){public void …

联盟链是虚构的?没有用的?用FISCO BCOS来展示链委员这件事

前言 当前区块链大都使用的是投票决定这种方法&#xff0c;但是如何使现实中的投票转换到区块链中&#xff0c;如何让举手表决变得更加智能&#xff0c;如何让投票透明、安全、权威&#xff0c;这是区块链的一大设计思路&#xff0c;有很多人觉得联盟链是个梦&#xff0c;是个虚…

计算机网络简史

ARPANET的发展 互联网最早的雏形 1931-ARPANET设计 互联网名人堂 1965-packet switching(分包交换) 1969 第一个RFC(Request for Comments)(开始通过APPANET发布)第一个接口信息处理单元&#xff08;Interface Message Processor&#xff09;&#xff08;下图&#xff0c;节…

制造企业该如何选择MES生产管理系统?盘点四大生产管理系统软件

本文将介绍&#xff1a;1、如何选择MES(生产管理系统&#xff09;&#xff1b;2、盘点四款好用的生产管理系统 生产管理系统即MES(Manufacturing Execution System)&#xff0c;制造执行系统。是面向车间生产的管理系统。在产品从工单发出到成品完工的过程中&#xff0c;MES系…

提取图像特征方法总结 是那种很传统的方法~

目录 写在前面 一、SIFT&#xff08;尺度不变特征变换&#xff09; 1.SIFT特征提取的实质 2.SIFT特征提取的方法 3.SIFT特征提取的优点 4.SIFT特征提取的缺点 5.SIFT特征提取可以解决的问题&#xff1a; 二、HOG&#xff08;方向梯度直方图&#xff09; 1.HOG特征提取…
最新文章