AnSwErYWJ's Blog

UNIX编程安全读写函数

字数统计: 399阅读时长: 8 min
2016/07/14

字节流套接字(TCP套接字)上的read和write函数所表现的行为不同于通常的文件I/O。字节流套接字调用read或write输入或输出的字节数可能比请求的数量少,然而这并不是出错的状态。这是因为内核中用于套接字的缓冲区可能达到了极限。通常这种情况出现在一次读多于4096个字节或write在非阻塞情况下返回不足字节数。为了不多次调用read或防止write返回不足字节数,我们用下面的两个函数来替代read和write。

readn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<stdio.h>
#include<unistd.h>
#include<errno.h>

ssize_t safe_read(int fd,void *vptr,size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;

ptr=vptr;
nleft=n;

while(nleft > 0)
{
if((nread = read(fd,ptr,nleft)) < 0)
{
if(errno == EINTR) //被信号中断,重读
nread = 0;
else //出错
return -1;
}
else if(nread == 0) //EOF
break;

nleft -= nread;
ptr += nread;
}
return (n-nleft);
}

writen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
#include<unistd.h>
#include<errno.h>

ssize_t safe_write(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;

ptr = vptr;
nleft = n;

while(nleft > 0)
{
if((nwritten = write(fd, ptr, nleft)) <= 0)
{
if(nwritten < 0 && errno == EINTR) //被信号中断,重写
nwritten = 0;
else //error
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}

总结

上面介绍了两个安全读写函数,但是并不意味着这两个函数在任何地方都完全适用,所以不要强迫自己使用。需要注意阻塞、效率等问题,当你只是读写少量字节时,就没必要使用了。

原文作者:AnSwErYWJ

原文链接:https://answerywj.com/2016/07/14/safe-read-and-write/

发表日期:2016/07/14 14:07

版权声明:本文采用Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License进行许可.
Creative Commons License

CATALOG
  1. 1. readn
  2. 2. writen
  3. 3. 总结