《UNIX网络编程 卷1》 笔记: readline函数 (不可重入版本)

网络编程中经常和一些基于文本行的协议打交道,典型的比如SMTP、HTTP等,所以需要一个从套接字中读取文本行的函数。本节我们写一个名为readline的函数实现这个功能。很缓慢的实现是每次调用read函数从套接字读取一字节然后判断是不是换行符(’ '),是换行符的话就返回。比较高效的实现是使用一个全局缓冲区read_buf,首先调用read函数读取一定量的数据放入read_buf,然后从read_buf中取出一行数据。代码如下:

#include "unp.h"

static char read_buf[MAXLINE]; /*4096字节大小的全局缓冲区*/
static int read_cnt; /*read_buf中待读取的字节数*/
static char *read_ptr; /*read_buf的读指针*/

/*从read_buf中读取1字节数据,返回成功读取的字节数*/
static ssize_t my_read(int fd, char *ptr)
{
	if (read_cnt <= 0) {
		again:
			if ((read_cnt = read(fd, read_buf, MAXLINE)) < 0) {
				if (errno == EINTR) /*重试*/
					goto again;
				return -1; /*read返回错误*/
			} else if (read_cnt == 0) /*遇到EOF*/
				return 0;
			read_ptr = read_buf;
	}
	read_cnt--;
	*ptr = *read_ptr++;
	return 1;
}

/*从套接字中读取一行数据,最大数据长度为maxlen*/
ssize_t readline(int fd, void *vptr, size_t maxlen)
{
	ssize_t n, rc;
	char c, *ptr;
	
	ptr = vptr;
	for (n = 1; n < maxlen; n++) {
		if ((rc = my_read(fd, &c)) == 1) { /*每次从buf中读取1字节*/
			*ptr++ = c;
			if (c == '
') /*已经读取一行数据*/
				break;
		} else if (rc == 0) { /*buf中无数据*/
			*ptr = 0;
			return n - 1;
		} else
			return -1;
	}
	*ptr = 0;
	return n;
}

/*包裹函数*/
ssize_t Readline(int fd, void *vptr, size_t maxlen)
{
	ssize_t n;
	if ((n = readline(fd, vptr, maxlen)) < 0)
		return -1;
	return n;
}

关于readline函数的使用,有以下几点注意的地方:
1. 由于使用全局变量,所以该函数是不可重入的。
2. 由于使用的是自定义的缓冲区而不是标准stdio缓冲区,所以该函数不能和select等系统调用一起使用。
3. 不能将该函数和上节实现的readn函数混用,因为它们使用的不是同一个缓冲区。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值