最近在编写利用套接口传输数据的程序时,发现如果直接利用read和write函数来实现对套接口数据的读写,若传输较小的文件基本上可以成功的传输和接受,但在传输较大文件,如百兆的视频文件时,则接受端会出现write error:bad address的情况。查了些资料,才将问题原因基本查明,总结如下:
字节流套接口上的read和write函数表现的行为不同于通常的文件I/O。字节流套接口上的读写字节数可能比要求的数量少,原因时内核中套接口的缓冲区可能已经达到极限。此时就需要调用者再次调用read和write函数,将剩余的字节输入和输出。有些版本的unix在往一个管道中写入多于4096字节的数据时会表现这样的行为。这种现象在读取套接口时很常见,在写字节流接口时只能在套接口非阻塞的情况下才出现。我们可以通过编写另外的readn函数和writen函数来预防这种现象。
ssize_t readn(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
{
perror("\nread");
return(-1);
}
}
else if(nread==0)
{
break;
}
nleft-=nread;
ptr =nread;
}
return(n-nleft);
}
ssize_t writen(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
{
perror("\nwrite");
return(-1);
}
}
nleft-=nwritten;
ptr =nwritten;
}
return (n);
}
通过使用readn和writen这两个自定义的函数,可以保证对套接口的读写是指定数量的字节数。
参考《UNIX网络编程》第一卷,套接口API
阅读(3600) | 评论(0) | 转发(0) |