网络编程 read 阻塞和非阻塞下的区别

1,read 原型,参数以及返回值。

#include <uinstd.h>
 
ssize_t read(int fd, void *buf, size_t nbytes);

-----read,只是将内核中缓冲区的数据搬到用户进程空间。

参数:

fd:某个连接的套接字。

buf:从内核缓冲区读入的数据放到用户缓冲区的地址。

nbytes:希望读入的数据大小,一般不是真正读人的大小。

返回值:实际读取的长度。

-1:error会被置为相应的值。

error:为EAGAIN,表示在非阻塞下,此时无数据到达,立即返回。

error:为EINTR,表示被信号中断了。

0:对端已关闭,本端也需要close 该套接字。

>0:实际读取的数据长度。

2,read 阻塞和非阻塞下的区别:
阻塞下
        原则是在不超过指定的长度下,有多少读多少,没有数据则一直等待,有可能会被信号中断。

       比如,对端write写了10字节,本端read 读20字节,则此时read 直接返回,不用等待数据到达20字节后再返回,返回的长度是10字节。        

非阻塞
       没有数据的话,返回-1,并置相应的error;有数据的话直接返回读入的数据大小,不超过指定的长度。

    比如,对端write写了10字节,本端read 只读5字节,则此时read 端返回5字节,剩下的5字节需要下次再读入,这种情况下需要循环读入。

3,read 循环读。

int nread(int fd, char *buf, int nbytes)
{
    int len = 0;
    int left = nbytes;
    char *ptr = buf;
    
    while(left)
    {
        len = read(fd, ptr, left);
        if(len == -1)
        {
            if(error == EAGAIN)
                len = 0;
            
        }
        if(len == 0)
        {
            close(fd);
            break;
        }
        left -= len;
        ptr += len;
    }
    return nbytes;
}

4,为什么read 不能一次性读完,需要循环来读?

        当fd为管道或socket时,对方数据多次发送或网络延时较大时,一次read 都可能只读到部分数据。(因为tcp是面向字节流的)

5,总结

read阻塞下非阻塞
无数据一直等待立马返回-1,error置为EAGAIN
有数据返回数据的大小(不超过指定的读入大小)返回数据的大小(不超过指定的读入大小)

————————————————
版权声明:本文为CSDN博主「u010765526」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010765526/article/details/89425129

心得:

1)read函数阻塞和非阻塞的区别,主要是缓冲区里没有数据的情况下,阻塞的话,会一直等,非阻塞的话,会立即返回,报错提醒。当缓冲区里由数据的情况下,二者是一样的。 

2)无论阻塞还是非阻塞,缓冲区里在不超过指定读的字节长度时,有多少立即返回多少。

3)read函数返回值为0,表示对端的socket已经关闭的理解:

以阻塞情况分析:假设对端没关闭,如果缓冲区没数据,read死等,

假设缓冲区有数据,read,返回不超过指定的字节数(>0);

错误返回-1;

也就是说,对于阻塞的情况,read只要返回了,如果没有发生过错误,就是读到数据了。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值