UNIX网络编程-recv、send、read、write之间的联系与区别

2023-11-19

原文链接:http://www.cnblogs.com/mhscn/p/3911284.html


include <unistd.h>

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

read()函数是负责从fd中读取内容。当读成功时,read()返回实际所读的字节数,如果返回的值是0,表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。我们写一个自己的读函数:

int my_read(int fd,void *buffer,int length) 
{
    int bytes_left; 
    int bytes_read; 
    char *ptr; 

    bytes_left=length; 

    while(bytes_left>0) 
    {
        bytes_read = read(fd,ptr,bytes_read); 
        if (bytes_read < 0) 
        {
            if(errno==EINTR)
                bytes_read=0; 
            else 
                return(-1); 
        }
        else if(bytes_read==0) 
            break; 

        bytes_left-=bytes_read; 
        ptr+=bytes_read; 
    }

    return(length-bytes_left); 
}

2、write

include <unistd.h>

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

write()函数将buf中的nbytes字节内容写入文件描述符fd,成功时返回写的字节数,失败时返回-1并设置errno变量。在网络程序中,当我们向套接字文件描述符写时有两可能:

1)write的返回值大于0,表示写了部分或者是全部的数据,这样我们用一个while循环来不停的写入,但是循环过程中的buf参数和nbyte参数得由我们来更新。也就是说,网络写函数是不负责将全部数据写完之后在返回的。

2)返回的值小于0,此时出现了错误,我们要根据错误类型来处理:

如果错误为EINTR表示在写的时候出现了中断错误。

如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

为了处理以上的情况,我们自己编写一个写函数来处理这几种情况。

int my_write(int fd,void *buffer,int length) 
{ 
    int bytes_left; 
    int written_bytes; 
    char *ptr; 

    ptr=buffer; 
    bytes_left=length; 

    while(bytes_left>0) 
    { 
        /* 开始写*/ 
        written_bytes=write(fd,ptr,bytes_left); 
        if(written_bytes<=0) /* 出错了*/ 
        {        
            if(errno==EINTR) /* 中断错误我们继续写*/ 
                written_bytes=0; 
            else             /* 其他错误没有办法,只好撤退了*/ 
                return(-1); 
        } 

        bytes_left-=written_bytes; 
        ptr+=written_bytes;     /* 从剩下的地方继续写  */ 
    } 

    return(0); 
} 

3、recv & send
recv和send函数提供了和read和write差不多的功能,不过它们提供了第四个参数来控制读写操作。

include <sys/types.h>

include <sys/socket.h>

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

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

前面的三个参数和一样,第四个参数可以是0或者是以下的组合:

| MSG_DONTROUTE | 不查找表 | 

| MSG_OOB | 接受或者发送带外数据 | 

| MSG_PEEK | 查看数据,并不从系统缓冲区移走数据 | 

| MSG_WAITALL | 等待所有数据 | 

MSG_DONTROUTE:是send函数使用的标志。这个标志告诉IP,目的主机在本地网络上面,没有必要查找表。这个标志一般用网络诊断和路由程序里面。

MSG_OOB:表示可以接收和发送带外的数据。关于带外数据我们以后会解释的。

MSG_PEEK:是recv函数的使用标志。表示只是从系统缓冲区中读取内容,而不清除系统缓冲区的内容,这样下次读的时候仍然是一样的内容。一般在有多个进程读写数据时可以使用这个标志。

MSG_WAITALL:是recv函数的使用标志。表示等到所有的信息到达时才返回。使用这个标志的时候recv会一直阻塞,直到指定的条件满足或者是发生了错误。

1)当读到了指定的字节时,函数正常返回。返回值等于len;

2)当读到了文件的结尾时,函数正常返回。返回值小于len;

3)当操作发生错误时返回-1,且设置错误为相应的错误号(errno)。

MSG_NOSIGNAL:is a flag used by send() in some implementations of the Berkeley sockets API.

This flag requests that the implementation does not to send a SIGPIPE signal on errors on stream oriented sockets when the other end breaks the connection. The EPIPE error is still returned as normal.

Though it is in some Berkely sockets APIs (notably Linux) it does not exist in what some refer to as the reference implementation, FreeBSD, which instead uses a socket option SO_NOSIGPIPE?.

对于服务器端,我们可以使用这个标志。目的是不让其发送SIG_PIPE信号,导致程序退出。

如果flags为0,则和read、write一样的操作。还有其它的几个选项,不过我们实际上用的很少。可以查看 Linux Programmer’s Manual得到详细解释。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UNIX网络编程-recv、send、read、write之间的联系与区别 的相关文章

  • Linux服务器上top后发现僵尸进程的解决办法

    今天在熟悉Linux命令的时候 使用top查看服务器负载的时候 发现了zombie 简单理解成僵尸吧 这个参数 这个参数就代表僵尸进程的含义 什么是僵尸进程呢 这里盗用一下官方的解释 一个进程在调用exit命令结束自己的生命的时候 其实它并
  • 解决com.xpand依赖引入问题

    引言 starter canal实现了springboot与canal的集成 比原生的canal更加优雅 下载地址 https github com chenqian56131 spring boot starter canal 使用前需要
  • 一:计算机基础入门及介绍

    计算机基础入门篇 1 计算机系统 计算机 Conputer 俗称电脑 一种能接收和存储信息 并按照存储在其内部的程序对海量数据进行自动 高速的处理 然后把处理结果输出的现代化智能电子设备 计算机有很多的形式类型 例如 生活中常见的家用电脑
  • chrome误删收藏夹书签如何恢复?

    打开书签管理器 按下Ctrl Z 然后就恢复了
  • python与excel做数据可视化-Python的Excel操作及数据可视化

    Excel表操作 python操作excel主要用到xlrd和xlwt这两个库 即xlrd是读excel xlwt是写excel的库 安装xlrd pip install xlrd 简单的表格读取 import xlrd 读取表格 data

随机推荐

  • emmc分区创建脚本

    bin sh add a new primary partition Param PartNum 1 3 First cylinder Last cylinder add partition echo creat primary parti
  • 深入理解Go——反射reflect

    文章目录 反射使用常见场景 反射原理 反射的基本函数 反射使用常见场景 需要反射的 2 个常见场景 有时你需要编写一个函数 但是并不知道传给你的参数类型是什么 可能是没约定好 也可能是传入的类型很多 这些类型并不能统一表示 这时反射就会用的
  • MySQL 库操作

    目录 创建数据库 语法 案例 字符集和校验规则 建数据库 建表用 查看系统默认字符集以及校验规则 db opt 更改 查看数据库支持的字符集 查看数据库支持的字符集校验规则 校验规则对数据库的影响 排升序 操纵数据库 查看数据库 显示创建语
  • 数据结构与算法学习(day4)——解决实际问题

    前言 在本章的学习此前 需要复习前三章的内容 每个算法都动手敲一遍解题 宁愿学慢一点 也要对每个算法掌握基本的理解 前面我们学习了简化版桶排序 冒泡排序和快速排序三种算法 今天我们来实践一下前面的三种算法 本章的学习目标 1 回顾三个算法的
  • openwrt ttyd 不能使用(修改lan口地址后)

    修改lan口地址后openwrt ttyd会被拒无法使用 解决办法如下 1 ssh 到openwrt的终端 2 编辑ttyd的配置文件 vim etc init d ttyd 3 将配置文件如下代码注释 interface i interf
  • Get,Post请求中文乱码问题有效解决方法

    对于做Java WEB项目同学来说 中文乱码问题是一个经常遇到而又非常头痛的问题 而最容易出现乱码的环节就是在浏览器向服务器发送请求的过程 至于出现乱码的原因不是本文的关注的重点 想了解的朋友可以参考 http zhaomin819111
  • GitHub设置头像

    在 GitHub 上随处可见的头像 账户独有的标识 是通过 Gravatar服务显示的 只要使用创建 GitHub 账户时注册的邮箱在 Gravatar 上设置头像 GitHub 的头像就会变成您设置好的样子 http cn gravata
  • 华为OD机试 - 解密犯罪时间(Java)

    题目描述 警察在侦破一个案件时 得到了线人给出的可能犯罪时间 形如 HH MM 表示的时刻 根据警察和线人的约定 为了隐蔽 该时间是修改过的 解密规则为 利用当前出现过的数字 构造下一个距离当前时间最近的时刻 则该时间为可能的犯罪时间 每个
  • 深度学习中的IoU概念理解

    1 什么是IoU Intersection over Union IoU是一种测量在特定数据集中检测相应物体准确度的一个标准 IoU是一个简单的测量标准 只要是在输出中得出一个预测范围 bounding boxex 的任务都可以用IoU来进
  • Delphi中关于资源释放(Free,Relealse,FreeAndNil)

    根据日常编程经验 得出一些Delphi中关于资源释放的体会 假如有对象Obj为TObject类型 1 Obj Free直接释放资源后 调用OnDestroy事件 但是没有将Obj指针值置为Nil 2 Obj Release 等待资源不再使用
  • Kali proxychains

    1 什么是proxychains 在linux系统中有很多软件是不支持代理的 但是proxychains 却可以让不支持代理的软件 也能走代理通道 支持HTTP HTTPS SOCKS4 SOCKS5 等多种代理协议 而且还能配置代理链 可
  • struct和typedef struct的用法和区别

    1 在C和C 里的不同 在c中定义一个结构体类型用typedef typedef struct Student int m Stu 用这种形式定义的时候 在声明结构体变量的时候可用 Stu stu1 这种形式也等同于struct Strde
  • Open3D (C++) 点云添加随机噪声

    Open3D C 点云添加随机噪声 在三维点云数据中 噪声是不可避免的 它可能是由于传感器测量误差 环境因素或其他未知影响造成的 为了模拟这些噪声 我们可以使用 Open3D 中提供的工具将噪声添加到点云数据中 本文将介绍如何使用 Open
  • postgres导入备份出现'无效的命令\N'

    在使用pg dump对数据库进行备份的时候 到出成默认的格式 导致插入数据时 提示无效的命令 N 解决方法 使用custom格式导出 然后用pg restore导入 导出 pg dump F custom U username d dbna
  • 下拉框,文本域和文件域

    p 国家 p
  • VS中报错IntelliSense: argument of type "void *" is incompatible with parameter of type "const char *"

    在用VS编写C 程序的时候 遇到这样的问题IntelliSense argument of type void is incompatible with parameter of type const char 但是给的例程确实传入参数就是
  • ListView的操作

    转自http blog sina com cn s blog 43eb83b90100mhrs html 这一篇对我也不错http blog csdn net xiaohan2826 article details 8603015 小白叔叔
  • PCIe 5.0 规范最新更新及PCIe 5.0测试挑战​

    PCIe 5 0 基础规范 v1 0 在 2019 年年中发布以后 Synopsys 发布了世界上第一款支持 PCIe 5 0 基础规范 v1 0 的 IP 并展示了在其实验室验证发射机 接收机 Tx Rx 性能的环境 Intel 也在 2
  • 基于MATLAB手写体数字识别程序设计

    基于MATLAB手写体数字识别程序设计 手写体识别由于其实用性 一直处于研究进步的阶段 本文主要针对的是对0 9十个手写数字体脱机识别 在Matlab中对样本部分为进行16特征的提取 分别采用最小距离法 最近邻法 KNN法以及BP神经网络算
  • UNIX网络编程-recv、send、read、write之间的联系与区别

    原文链接 http www cnblogs com mhscn p 3911284 html include