Skip to content

Instantly share code, notes, and snippets.

@lotusnowshen
Created August 12, 2015 03:59
Show Gist options
  • Select an option

  • Save lotusnowshen/152e4b929e6e282ac0ff to your computer and use it in GitHub Desktop.

Select an option

Save lotusnowshen/152e4b929e6e282ac0ff to your computer and use it in GitHub Desktop.
/**
* readn - 读取固定字节数
* @fd: 文件描述符
* @buf: 接收缓冲区
* @count: 要读取的字节数
* 成功返回count,失败返回-1,读到EOF返回<count
*/
ssize_t readn(int fd, void *buf, size_t count)
{
size_t nleft = count;
ssize_t nread;
char *bufp = (char*)buf;
while (nleft > 0)
{
if ((nread = read(fd, bufp, nleft)) < 0)
{
if (errno == EINTR)
continue;
return -1;
}
else if (nread == 0)
return count - nleft;
bufp += nread;
nleft -= nread;
}
return count;
}
/**
* writen - 发送固定字节数
* @fd: 文件描述符
* @buf: 发送缓冲区
* @count: 要读取的字节数
* 成功返回count,失败返回-1
*/
ssize_t writen(int fd, const void *buf, size_t count)
{
size_t nleft = count;
ssize_t nwritten;
char *bufp = (char*)buf;
while (nleft > 0)
{
if ((nwritten = write(fd, bufp, nleft)) < 0)
{
if (errno == EINTR)
continue;
return -1;
}
else if (nwritten == 0)
continue;
bufp += nwritten;
nleft -= nwritten;
}
return count;
}
/**
* recv_peek - 仅仅查看套接字缓冲区数据,但不移除数据
* @sockfd: 套接字
* @buf: 接收缓冲区
* @len: 长度
* 成功返回>=0,失败返回-1
*/
static ssize_t recv_peek(int sockfd, void *buf, size_t len) {
int nread;
while (1) {
//这个过程只成功调用一次
nread = recv(sockfd, buf, len, MSG_PEEK);
if (nread < 0 && errno == EINTR) { //被中断则继续读取
continue;
}
if (nread < 0) {
return -1;
}
break;
}
return nread;
}
/**
* readline - 按行读取数据
* @sockfd: 套接字
* @buf: 接收缓冲区
* @maxline: 每行最大长度
* 成功返回>=0,失败返回-1
*/
ssize_t readline(int sockfd, void *buf, size_t maxline) {
int nread; //一次IO读取的数量
int nleft; //还剩余的字节数
char *ptr; //存放数据的指针的位置
int ret; //readn的返回值
int total = 0; //目前总共读取的字节数
nleft = maxline-1;
ptr = buf;
while (nleft > 0) {
//这一次调用仅仅是预览数据
//并没有真的把数据从缓冲区中取走
ret = recv_peek(sockfd, ptr, nleft);
//注意这里读取的字节不够,绝对不是错误!!!
if (ret <= 0) {
return ret;
}
nread = ret;
int i;
for (i = 0; i < nread; ++i) {
if (ptr[i] == '\n') {
//这里才是真正的读取过程
ret = readn(sockfd, ptr, i + 1);
if (ret != i + 1) {
return -1;
}
total += ret;
ptr += ret;
*ptr = 0;
return total; //返回此行的长度 '\n'包含在其中
}
}
//如果没有发现\n,这些数据应全部接收
ret = readn(sockfd, ptr, nread);
if (ret != nread) {
return -1;
}
nleft -= nread;
total += nread;
ptr += nread;
}
*ptr = 0;
return maxline-1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment