UNIX编程安全读写函数——readn和writen

字节流套接字(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);
}

总结

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

About me

forthebadge

Creative Commons License This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。