发表文章 返回首页
当前位置: bitsCN.com > linux > 网络管理 > 网络管理 >

Linux下使用TCP通讯时遇到的问题

时间:2008-05-17 00:00来源:中国网管联盟 作者:bitsCN整理 点击:
在这里总结一下这linux用TCP通讯需要注意的几个问题,都是前一阵子工作中遇到的问题。 问题1. 发送和接收数据时的不完整问题 以接收为例,当对端发送1000个字节的数据时,本端进行接收,会出现调用recv返回500并且e
  

在这里总结一下这linux用TCP通讯需要注意的几个问题,都是前一阵子工作中遇到的问题。

网管联盟www.bitsCN.com

    问题1. 发送和接收数据时的不完整问题

中国网管联盟www.bitscn.com

    以接收为例,当对端发送1000个字节的数据时,本端进行接收,会出现调用recv返回500并且errno==EAGAIN的情况(测试中发现这种情况非常严重),这个错误表示当前设备忙,稍后再试。理想化的解决办法是这样的: 中国网管论坛bbs.bitsCN.com

    使用select或者epoll机制,当有数据到来时,select或epoll会通知,此时一直接收直到recv返回0表示所有数据都接收完。过程中当errno==EAGAIN则暂停接收,并将已经接收的数据缓存起来。当设备再次可读时select或者epoll会再次通知,在缓存数据的后面继续接收,如此反复n次直到recv返回值为0。

中国网管联盟www、bitsCN、com

    但是这种方法需要把已经接收的部分数据进行缓存,实现起来非常繁琐,我进行了如下的简单实现,是我封装的epoll中的部分代码: 中国网管联盟www、bitsCN、com

   

 int
mo_epoll_recv (int s, void* buf, int buf_size, int err)
{
int recved_len = 0;
int total_recv_len = 0;
int count = 0;

if (buf == NULL || buf_size <= 0)
{
return -1;
}

MO_DEBUG ("to recv some data!\n");

do
{
//MO_DEBUG ("call recv, total_recv_len=%d recv_len=%d\n", total_recv_len, buf_size-total_recv_len);
recved_len = recv (s, buf+total_recv_len, buf_size-total_recv_len, err);

//MO_DEBUG ("called recv, recved_len=%d\n, errno=%d:EAGAIN=%d:%s\n", recved_len, errno, EAGAIN, strerror (errno));

if (recved_len < 0 && errno != EAGAIN)
{
MO_ERROR ("some error when recv erron: %d, %s", errno, strerror (errno));
break;
}
else if (recved_len < 0 && errno == EAGAIN)
{
recved_len = 1;
/* 10s timeout */
if (++count > 200)
{
break;

54com.cn


}
usleep (1000*50);
continue;
}
total_recv_len += recved_len;
if (total_recv_len >= buf_size)
{
recved_len = 0;
//MO_DEBUG ("recv %d bytes!!!!!", total_recv_len);
break;
}
usleep (1000*50);
}while(recved_len > 0);
MO_DEBUG ("recv some data over %d bytes!\n", total_recv_len);

if (recved_len == -1)
return -1;

return total_recv_len;
}
int
mo_epoll_send (int s, const void* buf, int buf_size, int err)
{
int sended_len = 0;
int total_send_len = 0;

if (buf == NULL || buf_size <= 0)
{
return -1;
}
MO_DEBUG ("to send some data!\n");

do
{
sended_len = send (s, (buf+total_send_len), buf_size-total_send_len, err);
if (sended_len == -1 && errno != EAGAIN)
{
break;
}
else if (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 %d bytes!!!!!", total_send_len); 54ne.com
break;
}
}while(sended_len > 0);
MO_DEBUG ("send some data over %d bytes!\n", total_send_len);

if (sended_len == -1)
return -1;

return total_send_len;
}
中国网管联盟www、bitsCN、com

    问题2. 干净的关闭socket,应该使用如下方法来关闭你不使用的socket,不要仅仅调用close(): 网管网bitsCN_com

   

 cleanclose (int s)
{
int i = 0;
char buf[100];
/* 关闭写入 */
shutdown (s, SHUT_WR);
/* 接收所有数据 */
do
{
i = recv (s, buf, 100, 0);
}while (i > 0);
/* 关闭读取 */
shutdown (s, SHUT_RD);

/* 关闭socket */
close (s);
}
中国网管论坛bbs.bitsCN.com

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
发布者资料
admin 查看详细资料 发送留言 加为好友 用户等级:注册会员 注册时间:2008-05-08 23:05 最后登录:2009-01-06 00:01
推荐内容