网络编程-libevnet编程整理一些小事项
4.1 发送缓冲区设定
Libevent库默认是4096字节,也就是4k,超过这个将分包处理,也可以使用放大缓存区的大小,一次性回调来接受数据。
具体操作:
- 在accept回调中获取到socket套接字后设置一下socket缓冲区大小
- 修改libevent源码的EVBUFFER_MAX_READ改大(改好后重新编译libevent)
- 调用bufferevent_set_max_single_read
int nRecvBuf=1024*10;//设置为32K
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
bufferevent_set_max_single_read(bufEV, 1024*10);
bufferevent_set_max_single_write(bufEV, 1024*10);
4.2 断开连接定时器使用
服务器向断开客户端连接,在客户端中回到函数中直接调用event_base_loopbreak,退出事件循环无效,在这里可以使用定时器来操作,采用定时器来监控某个变量。
void TimeCallback(int nSock, short sWhat, void * pArg)
{
CHttpServer *pHttpServer = (CHttpServer *)pArg;
bufferevent_enable(pHttpServer->bufEV, EV_READ|EV_WRITE|EV_PERSIST);
if( 0 !=pHttpServer->m_nState )
{
LOG_INFO("handle_timeout closed\n");
event_base_loopbreak(pHttpServer->baseEV);
}
}
struct event eTimeout;
struct timeval tTimeout = {10, 0};
event_assign(&eTimeout,baseEV, sockfd, EV_PERSIST, TimeCallback, this);
evtimer_add(&eTimeout, &tTimeout);
4.3 分包接受,然后组装
代码如下:
int count=0;
char buf_data[1024*10]={0};
int overall_data_length=0;
int recv_one_length=0;
int iStopRecv=1;
#define BUF_SHORT 4096
void ReadCallback( struct bufferevent * pBufEv, void * pArg )
{
char recv_one__data[BUF_SHORT] = {0};
msg_header header;
struct evbuffer *in =bufferevent_get_input(pBufEv);
printf("Received %zu bytes\n",evbuffer_get_length(in));
int cur_buf_size=evbuffer_get_length(in);
count++;
printf("************%d****************\n", count);
recv_one_length += bufferevent_read(pBufEv, recv_one__data, sizeof(recv_one__data));
printf("len:%d,MsgHeader.sizeof=%d\n",recv_one_length,sizeof( msg_header));
if(iStopRecv)
{
iStopRecv=0;
if (recv_one_length < sizeof( msg_header))
{
printf( "buf len <sizeof( msg_header)\n" );
return ;
}
memcpy(&header, recv_one__data, sizeof( msg_header));
if ( header.head[0] != 'H' || header.head[1] != 'K' || header.head[2] != 'P' || header.head[3] != '&' )
{
printf("head:%s", header.head);
return ;
}
overall_data_length=header.pack_len;
printf("overall_data_length:%d,recv_one_length:%d,cur_buf_size:%d\n",overall_data_length, recv_one_length,cur_buf_size);
strcpy(buf_data+recv_one_length-cur_buf_size,recv_one__data+sizeof(msg_header));
if (overall_data_length >recv_one_length - sizeof(msg_header))
{
printf("header.pack_len:%d\n", header.pack_len);
return ;
}
}
else
{
strcpy(buf_data+recv_one_length-cur_buf_size-sizeof( msg_header),recv_one__data);
if (overall_data_length > recv_one_length - sizeof( msg_header))
{
printf("overall_data_length:%d,recv_one_length:%d",overall_data_length,recv_one_length);
return ;
}
}
recv_one_length=0;
iStopRecv=1;
printf("buf_data:%s\n",buf_data);
printf("recv end !!!");
}
4.4 阻塞设置
kill掉server进程,然后立刻restart这个server,如果在bind()之前不设置SO_RESUEABLE,将返回错误,因为TIME_WAIT状态的存在,这些TCP链接将占有当前[ip,port]二元组,一般情况下TIME_WAIT状态将持续2分钟左右,安全的做法是等待TIME_WAIT状态的结束
参考:
https://blog.csdn.net/shuiyanmei/article/details/79296919
https://blog.csdn.net/zhangxiao93/article/details/70195067
https://blog.csdn.net/luotuo44/article/details/39547391