readn/writen(接收/发送) 方法封装

前言

通常文件的I/O与字节流套接字上的read和write函数所表现的行为不一样,有时候字节流套接字上调用read和write返回的字节数可能比请求的大小要小,而这样并不表示一个错误,如果在内核中用于套接字的缓冲区满了达到上限了,这时候就需要再次调用read或write函数,因此封装了如下的两个小函数。
在封装的函数里面如果遇到EINTR错误(说明调用被中断)或EAGAIN(可以尝试再读一次),这时候应该继续读或写,以此来处理剩下的字节

/* code from UNIX Network Programing by W.Richard Stevens */
ssize_t readn(int fd, void *vptr, ssize_t n)
{
	ssize_t nleft,nread;
	char *ptr;
	if(fd == -1)
		return -1;
	ptr = vptr;
	nleft = n;
	while(nleft > 0)
	{
		if((nread = recv(fd, ptr, nleft, 0)) < 0)
		{
			if(errno == EINTR || errno == EAGIAN)
				nread = 0;
			else 
			{
				perror("read");
				return -1;
			}
		} else if(nread == 0) {
			break;
		}
		nleft -= nread;
		ptr += nread;
	}
	
	return (n - nleft);
}
/* code from UNIX Network Programing by W.Richard Stevens */
ssize_t writen(int fd, void *vptr, ssize_t n)
{
	ssize_t nleft,nwritten;
	char *ptr;
	if(fd == -1)
		return -1;
	ptr = vptr;
	nleft = n;
	while(nleft > 0)
	{
		if((nwritten = write(fd, ptr, nleft, 0)) < 0)
		{
			if(errno == EINTR || errno == EAGIAN)
				nwritten = 0;
			else 
			{
				perror("write");
				return -1;
			}
		} else if(nwritten == 0) {
			perror("write ret 0");
			syslog(LOG_ERR, "write err(%s:%d)", __FILE__, __LINE__);
			return -1;
		}
		nleft -= nwritten;
		ptr += nwritten;
	}
	
	return (n - nleft);
}

另外附上一篇介绍select实现[超时]检测:read_timeout;write_timeout;connect_timeout;accept_timeout的文章
https://blog.csdn.net/weixin_36750623/article/details/83307973

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值