一般可以把session和read_buffer和write_buffer封装成结构体。 session可以是单一的fd,也可以是fd和其相关信息的再封装。
形如:
typedef struct sStream {
int fd; /*session*/
unsigned int max_buffer_size; /*读写buffer最大值*/
void* read_buffer;
unsigned int read_buffer_len; /*已有数据长度*/
void* write_buffer;
unsigned int write_buffer_len; /*已有数据长度*/
}Stream;
这样封装起来实质上就是在内核fd的缓冲区机制上又在应用层加了一个缓冲机制。 这样就可以把内核层的read和write封装成我们自己的read API和write API。应用方法大略如下:
write:
比如自己封装的write API为: int self_write(Stream* st, void* buf, unsigned int len);
/*输入参数正确的前提下*/
int write_direct(Stream* st, void* buf, unsigned int len)
{
int count = 0;
int left = len;
const char* cur_buf = buf;
while(left > 0)
{
count = write(st->fd, cur_buf, left);
if (count < 0)
{
if (left == len)
return -1;
else
return len - left;
}
left -= count;
cur_buf += count;
}
return len;
}
int write_fresh(Stream* st)
{
char* buf = st->write_buffer;
int len = st->write_buffer_len;
int count = 0;
while (len > 0)
{
count = write(st->fd, buf, len);
if (count < 0)
{
memmove(st->write_buffer, buf, left);
st->write_buffer = left;
return -1;
}
len -= count;
buf += count;
}
st->write_buffer_len = 0;
return 0;
}
int write_internal_buffer(Stream* st, void* buf, unsigned int len)
{
memcpy(st->write_buffer + st->write_buffer_len, buf, len);
st->write_buffer_len += len;
return len;
}
int self_write(Stream* st, void* buf, unsigned int len )
{
unsigned int count = len;
unsigned int buf_len = st->write_buffer_len;
int iRet = -1;
if ( count + len > st->max_buffer_size)
{
iRet = write_fresh(st);
if (iRet == -1)
return -1;
if (count > max_buffer_size)
{
iRet = write_direct(st, buf, len);
return iRet;
}
}
iRet = write_internal_buffer(st, buf, len);
return iRet;
}
read:
比如自己封装的read API为: int self_read(Stream* st, void* buf, unsigned int len);
/*输入参数正确的前提下*/
int read_from_internal_buffer(Stream* st, void* buf , unsigned int len) /*从内部buffer中读, 有指针移动*/
{
memcpy(buf, st->read_buffer, len);
memmove(st->read_buffer, st->read_buffer + len; st->read_buffer_len - len);
st->read_buffer_len -= len;
return len;
}
int read_flush(Stream*st, void* buf) /*把buffer中的所有都读出来*/
{
int len = st->read_buffer_len;
memcpy(buf, st->read_buffer, len);
st->read_buffer_len = 0;
return len;
}
int read_direct(Stream* st, void* buf, unsigned int len) /*直接从网络读取*/
{
int readen = 0;
int left = len;
char* cur_buf = buf;
while(left > 0)
{
readen = read(st->fd, cur_buf, left);
if (readen == -1)
{
if (left == len)
return -1;
else
return len - left;
}
left -= readen;
cur_buf += readen;
}
return len;
}
int read_to_buffer(Stream* st) /*填满内部buffer,起初是空的*/
{
int count = 0;
int len = st->max_buffer_size ;
char* buf = st->read_buffer ;
while(len > 0)
{
count = read(st->fd, buf, len);
if (count == -1)
{
if (len == st->max_buffer_size )
return -1;
else
return st->max_buffer_size - len;
}
len -= count;
buf += count;
}
st->read_buffer_len = st->max_buffer_size;
return st->max_buffer_len;
}
int self_read(Stream* st, char* buf, unsigned int len)
{
int iRet = -1;
int writen = 0;
if (len <= st->read_buffer_len) /*如果内部buffer数据够用*/
{
iRet = read_from_internal_buffer(st, buf, len); /*直接读fd的内部buffer*/
return iRet;
}
else /*内部buffer数据不够用*/
{
writen = read_flush(st, buf); /*先把内部buffer数据全读出来*/
len -= writen;
buf += writen;
if (len > st->max_buffer_size) /*上面读完之后还需要的数据大于buffer容量*/
{
iRet = read_direct(st, buf, len); /*直接从fd读*/
if (iRet == -1)
return writen;
else
return writen + iRet;
}
/*上面读完之后还需要的数据量小于buffer的容量*/
iRet = read_to_buffer(st); /*先从fd把内部buffer读满*/
if (iRet == -1)
return writen;
iRet = read_from_internal_buffer(st, buf, len); /*再从内部buffer读余下的数据*/
return writen + iRet;
}
}
以上代码只是简单地把buffer运用思想体现出来了,真正用的时候还需要判断各种临界条件,参数合法性等。