免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7401 | 回复: 13
打印 上一主题 下一主题

两个问题:一、系统缓冲区到socket缓冲区的问题;二、EAGAIN问题。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-06-26 10:12 |只看该作者 |倒序浏览
本帖最后由 forward_ding 于 2012-06-26 10:35 编辑

问题一、
请教下:为send设置了不经历由系统缓冲区到socket缓冲区的拷贝,这跟不设置有什么不同(除了网络上说的性能提升外)?
数据经过系统缓冲区有什么好处?


问题二、
我现在程序有个问题:很容易出现EAGAIN(资源暂时不可用),程序用的是libevent封装的epoll,按照网上的说法有三种解决方法:
1.调大tcp_sendspace,使之大于send中的size参数。
但我觉得生产机参数一般不宜调吧,况且有多台;
2.在调用send前,在setsockopt函数中为SNDBUF设置更大的值。
这个倒是设置了,但是还是经常有EAGAIN出现;
3.使用write替代send,因为write没有设置O_NDELAY或者O_NONBLOCK
这个没有试,主要是考虑socket还是用send比较好,可以设置一些带外参数。

我也尝试在包裹函数中像处理EINTR中断一样处理EAGAIN,但后来发现过一段时间后程序cpu占用很严重,并且从日志观察到程序不处理数据了,像死循环。包裹函数如下:
  1. /* Write "n" bytes to a descriptor. */
  2. int mysend(unsigned int fd, const void *vptr, int n)
  3. {
  4.     errflag = 0;
  5.     int nleft;
  6.     int nwritten;
  7.     const char *ptr;

  8.     ptr = vptr;
  9.     nleft = n;
  10.     while (nleft > 0)
  11.     {
  12.         if ((nwritten = send(fd, ptr, nleft, 0)) <= 0)
  13.         {
  14.             errflag = 1;
  15.             int errtmp = errno;
  16.             if (errtmp == EINTR || errtmp == EAGAIN)
  17.                 nwritten = 0;  /* and call write() again */
  18.             else
  19.             {
  20.                 LOG_ERROR(chatlog, "send message to fd %d error : %s", fd, strerror(errtmp));
  21.                 return(errtmp);   /* error */
  22.             }
  23.         }

  24.         nleft -= nwritten;
  25.         ptr   += nwritten;
  26.     }
  27.     return(n);
  28. }
复制代码

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
2 [报告]
发表于 2012-06-26 10:20 |只看该作者
用select/poll/epoll之类的

论坛徽章:
0
3 [报告]
发表于 2012-06-26 10:34 |只看该作者
楼上什么意思呢?我用的是libevent封装的epoll

论坛徽章:
0
4 [报告]
发表于 2012-06-26 11:09 |只看该作者
随便扯下阿,socket的资源暂时不可用大多是因为你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误。write本身就是阻塞的io把,所以不会有这个问题。这个你要仔细找找是不是非阻塞的情况下没有数据可用(发送或者接受没有数据)

论坛徽章:
0
5 [报告]
发表于 2012-06-26 12:35 |只看该作者
第一个问题,增加缓冲区是为了减少网络IO,这对于频繁少量数据性能提升很明显,不用缓冲区的话,发送的数据会立即进入网络通道,而且如果网络忙的话,应该会更容易出错。

论坛徽章:
0
6 [报告]
发表于 2012-06-26 12:46 |只看该作者
ibinliu 发表于 2012-06-26 11:09
随便扯下阿,socket的资源暂时不可用大多是因为你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这 ...


前提本身就是非阻塞模式下调用了阻塞操作,应该不会有其它情况导致EAGAIN了吧?

论坛徽章:
0
7 [报告]
发表于 2012-06-26 13:01 |只看该作者

EAGAIN下次再写 非阻塞还想一次性搞定就没意义了。performance was killed。

论坛徽章:
0
8 [报告]
发表于 2012-06-26 13:13 |只看该作者
本帖最后由 forward_ding 于 2012-06-26 13:14 编辑
huxk 发表于 2012-06-26 13:01
EAGAIN下次再写 非阻塞还想一次性搞定就没意义了。performance was killed。


epoll是基于事件触发的,并且我一份数据是发给多个客户端的,你的下次是指把发生EAGAIN的fd和发送的数据保存起来,过几毫秒再发?这种实现起来不知是否麻烦,我也曾经考虑过。

论坛徽章:
0
9 [报告]
发表于 2012-06-26 13:18 |只看该作者

epoll要一个可用的程序本身就麻烦,代码量和阻塞相比要成倍翻。如果客户端不上万就用阻塞的吧。非阻塞不符合人类思维习惯。

论坛徽章:
0
10 [报告]
发表于 2012-06-26 13:29 |只看该作者
huxk 发表于 2012-06-26 13:18
epoll要一个可用的程序本身就麻烦,代码量和阻塞相比要成倍翻。如果客户端不上万就用阻塞的吧。非阻塞不符 ...


代码量不大,倒是内存开销太大(需要额外的变量保存客户端的某些逻辑数据处理),已经上万了,还有更好的方法吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP