部分读和部分写的原因及处理方法

本文介绍了如何处理在执行read、write、recv及send操作时可能遇到的部分读写问题,包括被信号打断等情况,并提供了具体的代码实现。

部分读写是指,执行read或者write操作时,读取的或者写入的字节数小于请求的字节数。

部分读的原因有两个,一是接近文件末尾(EOF),二是被信号打断。

部分写的原因也是被信号打断。

其实,recv和send也会出现部分接收或者发送的情况,其原因都是被信号打断。

即使使用MSG_WAITALL这个标志,也会被信号打断。这个标志类似于下面的循环,不过不对EINTR处理。

(其他原因参考man手册,此处不做赘述)

那么,为了处理这种情况,只需要对信号打断情况进行处理即可,此时read,write,recv,send返回-1,errno=EINTR。

ssize_t readn(int fd, void *buf, size_t n)
{
    ssize_t numRead;
    size_t totRead;
    char * buffer;
    buffer = buf;
    for(totRead = 0; totRead < n;)  
    {
        numRead = read(fd, buffer, n - totRead);
        if(0 == numRead)
            return totRead;
        if(-1 == numRead)
        {
            if(EINTR == errno)
                continue;
            else
                return -1;
        }
        totRead += numRead;
        buffer += numRead;
    }
    return totRead;
}
ssize_t writen(int fd, const void * buf, size_t n)
{
    ssize_t numWritten;
    size_t totWritten;
    char * bufffer;
    buffer = buf;
    for(totWritten = 0; totWritten < n;)
    {
        numWritten = write(fd, buffer, n - totWritten);
        if(-1 == numWritten)
        {
            if(EINTR == errno)
                continue;
            else
                return -1;
        }
        totWritten += numWritten;
        buffer += numWritte;
    }
    return totWritten;
}
ssize_t recvn(int sockfd, void * buf, size_t n, int flags)
{
    ssize_t numRecv;
    size_t totRecv;
    char * buffer;
    buffer = buf;
    for(totRecv = 0; totRecv < n;)
    {
        numRecv = recv(sockfd, buffer, n - totRecv, flags);
        if(0 == numRecv)
            return totRecv;// peers has performed an orderly shutdown.
        if(-1 == numRecv)
        {
            if(EINTR == errno)
                continue;
            else
                return -1;
        }
        totRecv += numRecv;
        buffer += numRecv;
    }
    return numRecv;
}
ssize_t sendn(int sockfd, const void * buf, size_t n, int flags)
{
    ssize_t numSend;
    size_t totSend;
    char * buffer;
    buffer = buf;
    for(totSend = 0; totSend < n;)
    {
        numSend = send(sockfd, buffer, n - totSend, flags);
        if(-1 == numSend)
        {
            if(EINTR == errno)
                continue;
            else
                return -1;
        }
        totSend += numSend;
        buffer += numSend;
    }
    return totSend;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值