字节流套接字(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) 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 return -1; } nleft -= nwritten; ptr += nwritten; } return(n); }
|
总结
上面介绍了两个安全读写函数,但是并不意味着这两个函数在任何地方都完全适用,所以不要强迫自己使用。需要注意阻塞、效率等问题,当你只是读写少量字节时,就没必要使用了。