|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
学习linux,就意味着更快的开发效率,等更多关于软件本身或者说操作系统本身的理解。
在这里总结一下这linux用TCP通信必要注重的几个成绩,都是前一阵子事情中碰到的成绩。
成绩1.发送和吸收数据时的不完全成绩
以吸收为例,当对端发送1000个字节的数据时,本端举行吸收,会呈现挪用recv前往500而且errno==EAGAIN的情形(测试中发明这类情形十分严峻),这个毛病暗示以后设备忙,稍后再试。幻想化的办理举措是如许的:
利用select大概epoll机制,当无数据到来时,select或epoll会关照,此时一向吸收直到recv前往0暗示一切数据都吸收完。过程当中当errno==EAGAIN则停息吸收,并将已吸收的数据缓存起来。当设备再次可读时select大概epoll会再次关照,在缓存数据的前面持续吸收,云云重复n次直到recv前往值为0。
可是这类办法必要把已吸收的部分数据举行缓存,完成起来十分烦琐,我举行了以下的复杂完成,是我封装的epoll中的部分代码:
int
mo_epoll_recv(ints,void*buf,intbuf_size,interr)
{
intrecved_len=0;
inttotal_recv_len=0;
intcount=0;
if(buf==NULL||buf_size<=0)
{
return-1;
}
MO_DEBUG("torecvsomedata!
");
do
{
//MO_DEBUG("callrecv,total_recv_len=%drecv_len=%d
",total_recv_len,buf_size-total_recv_len);
recved_len=recv(s,buf+total_recv_len,buf_size-total_recv_len,err);
//MO_DEBUG("calledrecv,recved_len=%d
,errno=%d:EAGAIN=%d:%s
",recved_len,errno,EAGAIN,strerror(errno));
if(recved_len<0&&errno!=EAGAIN)
{
MO_ERROR("someerrorwhenrecverron:%d,%s",errno,strerror(errno));
break;
}
elseif(recved_len<0&&errno==EAGAIN)
{
recved_len=1;
/*10stimeout*/
if(++count>200)
{
break;
}
usleep(1000*50);
continue;
}
total_recv_len+=recved_len;
if(total_recv_len>=buf_size)
{
recved_len=0;
//MO_DEBUG("recv%dbytes!!!!!",total_recv_len);
break;
}
usleep(1000*50);
}while(recved_len>0);
MO_DEBUG("recvsomedataover%dbytes!
",total_recv_len);
if(recved_len==-1)
return-1;
returntotal_recv_len;
}
int
mo_epoll_send(ints,constvoid*buf,intbuf_size,interr)
{
intsended_len=0;
inttotal_send_len=0;
if(buf==NULL||buf_size<=0)
{
return-1;
}
MO_DEBUG("tosendsomedata!
");
do
{
sended_len=send(s,(buf+total_send_len),buf_size-total_send_len,err);
if(sended_len==-1&&errno!=EAGAIN)
{
break;
}
elseif(sended_len==-1&&errno==EAGAIN)
{
sended_len=1;
continue;
}
total_send_len+=sended_len;
if(total_send_len>=buf_size)
{
sended_len=0;
//MO_DEBUG("send%dbytes!!!!!",total_send_len);
break;
}
}while(sended_len>0);
MO_DEBUG("sendsomedataover%dbytes!
",total_send_len);
if(sended_len==-1)
return-1;
returntotal_send_len;
}
成绩2.洁净的封闭socket,应当利用以下办法来封闭你不利用的socket,不要仅仅挪用close():
cleanclose(ints)
{
inti=0;
charbuf[100];
/*封闭写进*/
shutdown(s,SHUT_WR);
/*吸收一切数据*/
do
{
i=recv(s,buf,100,0);
}while(i>0);
/*封闭读取*/
shutdown(s,SHUT_RD);
/*封闭socket*/
close(s);
}
</p>
如果你想在以后的生涯中在软件行业工作的话,学习linux是一项基本技能,所以打从你打算学习linux那天起,放弃windows吧!因为它除了能给你带来片刻的娱乐,别无其他; |
|