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

1,write原型,参数及返回值。

#include <unistd.h>

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

    ------函数write 只是将用户进程中的数据拷贝到内核缓冲区中,拷贝数据的大小取决于内核缓冲区的大小与nbytes。

参数:

fd:标示某个套接字;

buf:进程中需要往对端发送的数据;

nbytes:需要发送的数据长度。

返回值:

   -1:相应的错误码会写到error中。

         error :EAGAIN 或 EWOULDBLOCK,表示缓冲区已满,此时无法写入,需要等待下次机会。(EAGAIN和EWOULDBLOCK 两者本质一样,只是分别用于不同的系统,前者是gnu,即linux,后者是bsd系统,都表示缓冲区已满,无空间可写)

         error:EPIPE,这是一种典型的错误场景,当client A 已经关闭了,server B 由于网络延迟等原因未察觉,依然向这个已关闭的fd,执行write时,内核会向B 返回 EPIPE错误码,并产生SIGPIPE,默认情况下,进程对该信号的动作是自动退出,所以一般服务器需要处理该信号。

  >0:写入内核缓冲区的数据大小。

  =0:返回一般不会为0,根据第3个参数的值,如果为0,则表示啥都不执行,write返回0。

 

2,write 在阻塞和非阻塞下的区别。

  • 阻塞下

        当内核缓冲区大小不足以容纳需要写入的 nbytes,write一直阻塞等待,直到缓冲区大小 >= nbytes 时,write一次性copy,等待的过程中,有可能会被信号中断。

       当内核缓冲区大小能够容纳需要写入的nbytes,write copy到缓冲区,并返回 nbytes。

  • 非阻塞

       坚持的原则是有多少写多少,如果内核缓冲区空间足够,同阻塞情况,一次性copy;如果缓冲区不够,则缓冲区的大小是有多少就写入多少,并返回该值,显然返回值小于nbytes,此种情况需要循环的方式将nbytes数据写到缓冲区;如果缓冲区是满的,则返回-1,并置error值为EAGAIN 或 EWOULDBLOCK。

 

3,write 的循环写入。

int nwrite(int fd, char *buf, int nbytes)
{
    int len = 0;
    char *ptr = buf;
    int left = nbytes;
    while(left)
    {
         len = write(fd, ptr, left);
         if(len < 0)
         {
            if(error == EAGAIN)
                len = 0;
            else
                return -1;    //真正的错误
         }
         if(len == 0)
         {
             break;
         }
         left -= len;
         ptr += len;
    }
    return nbytes;
}

4,write 遗留几个问题?

     write非阻塞的时候需要检测中断吗?

     write一次性能最大写入缓冲区多少字节?

5,总结

write阻塞下非阻塞
缓冲区满一直等待返回-1,并置error为EAGAIN
有缓冲区,但不够指定写的大小一直等待,直到有足够空间写入一部分,并返回该写入的部分大小
有缓冲区,而且大小也够一次性写入一次性写入

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值