本文将记录如何封装基于socket的网络发送与接收接口(非阻塞)
1. 接收
参数:void *buffer, int length
当我们需要从网络中接收一定长度的数据时,不能单纯只调用相应的socket recv就可以了,通常我们
需要考虑当前系统及网络的情况:
1)一次性接收成功
这是最简单和理想的情况,所期望接收的数据通过socket能够一次性成功,即recv返回长度和期望接收length一致。
此时可直接返回;
2)接收成功,但未完全接收期望的数据
针对这一种情况,可以有两种处理方式:
a. 可以立马返回,由更上层调用者负责处理是否重新调用此接口来完成剩余数据的接收;
b. 如果想在此接口中处理,则通常的做法是在while循环中处理接收操作,只至全部数据接收完成后退出循环后返回。具体操作示例
如下:
char * pos = (char*)buffer;
do
{
recvLength = recv(pos, length);
length -= recvLength;
//buffer的指针移位
pos += recvLength;
}while(length>0)
3) 接收等待,设置超时
当socket接收函数返回EWOULDBLOCK的状态时,表示接收并未成功,需要等待。此时,我们需要对socket进行
监听,必要时加入超时机制,以下展示了如何操作:
if (ret == EWOULDBLOCK )
{
int selectRet = select(socket + 1, xxx, xxx); //对socket读FD进行监听
if ( selectRet == 0 ) // timeout
{
// do something
}
else if ( selectRet < 0 ) // error
{
// do something
}
}
else //接收成功
{
<pre name="code" class="cpp">//do something,通常做
<pre name="code" class="cpp">length -= recvLength;
//buffer的指针移位
pos += recvLength;
}
当然,以上几种情况在真实写代码时,需要有机结合起来,成为一体。结构如下:
do
{
// call recv function;
if ( EWOULDBLOCK)
{
do select()
if( selectRet == 0 )
{
return;
}
else if(selectRet < 0 )
{
return; //error
}
}
else //接收成功
{
pos += recvLength;
length -= recvLength;
}
}while(length > 0 )
return ok;
2.发送
发送的流程情况和接收类似,操作也雷同,不同的地方是当遇到EWOULDBLOCK时,需要select socket的写FD。