免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: maxmaxsh
打印 上一主题 下一主题

socket 超时问题如何解决 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2008-07-24 15:34 |只看该作者
原帖由 converse 于 2008-7-24 15:10 发表
没懂,像前面的人说的发送心跳包的策略为什么不可以?如果client针对某个心跳包也发送了自己的回复,那么就继续存活,否则close掉连接.



很简单的情况,
假设 客户端是一个telnet,客户端在连上我以后就走了。

他连上来, 我发一个心跳数据包给他, 记录一下时间点, 他接受完成, 我开始使用recv , 将socket   放入epoll, 等他的心跳消息的回复。

如果连接已经断开,那么我很快能知道。

如果他没有断开, 我的recv 是不会从epoll 里面返回,我怎么断开他?

所以他没有回复,你也没法close掉它。

论坛徽章:
0
12 [报告]
发表于 2008-07-24 17:10 |只看该作者
你发送完心跳就返回了,继续监听,为什么还阻塞在那recv,不然用select干撒?

[ 本帖最后由 yuangong 于 2008-7-24 17:12 编辑 ]

论坛徽章:
0
13 [报告]
发表于 2008-07-24 17:26 |只看该作者
我用 epoll 不是select 好不好。

send 成功,然后继续监听, select 可以超时返回,

epoll 可以吗?epoll不能在超时返回, 我怎么断掉它?

[ 本帖最后由 maxmaxsh 于 2008-7-24 17:29 编辑 ]

论坛徽章:
0
14 [报告]
发表于 2008-07-24 17:31 |只看该作者
原帖由 maxmaxsh 于 2008-7-24 17:26 发表
我用 epoll 不是select 好不好。

send 成功,然后继续监听, select 可以超时返回,

epoll 可以吗?不能的化, 我怎么断掉它?

你不是有个时间戳么?当然如果你只poll一个socket,可以直接用poll的超时,否则的话只能另想办法对所有的socket进行轮训了,取当前时间和时间戳进行比较了。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
15 [报告]
发表于 2008-07-24 18:07 |只看该作者
1. 如果你做的是内部服务. 那就让客户端主动发心跳. 服务器只定时检查客户端是不是丢失心跳就OK了.
2. 如果你做的是开放平台. 那么就模仿libevent. 给每个连接作一个类时器. 规定每个socket的空闲时间.
    定时器就由select来驱动.
3. 为每个会话. 搞一个状态机. 定时器检查每个状态是否超时. 接收到连接.没有收到数据时.是一个状态.

论坛徽章:
0
16 [报告]
发表于 2008-07-24 20:32 |只看该作者
原帖由 maxmaxsh 于 2008-7-24 17:26 发表
我用 epoll 不是select 好不好。

send 成功,然后继续监听, select 可以超时返回,

epoll 可以吗?epoll不能在超时返回, 我怎么断掉它?


谁给你说的epoll没法超时返回?
首先你思路混乱阿伙计。
给你说下apache 的keepalvie的实现,在客户端keep-alvie的时候,apache需要检测客户端是否超时,和你的需求一样。
首先在你的epoll线程 将你的句柄在epoll_wait的时候设置上超时,如1s,此处就是为了让他超时,超时干嘛尼,就是为了
让它有功夫检测一个存储超时时间项目的队列,这个队列里有客户端句柄和其对应的expire time,到这里你也该想到这个队列的时间应该有人维护,
谁哪?就是你处理用户请求的线程,在那里你可以根据处理情况,重设或者删除队列里对应你的超时项。

这样apache就用一个epoll线程兼职维护了所有的keep-alive连接,这样做也是为了不让这些连接占用较多的工作线程。
这个地方是基本不影响接收连接的。因为你的工作线程参与维护这个队列,所以对这个队列的操作是需要加锁的。

在有超时项目的时候,apache是将该项目从队列删除后,将句柄交给工作线程处理的,这样是尽量避免epoll线程受
影响,也符合设计思路。

上面说的是apache 的实验版epoll mpm的实现。

你的问题似乎是在一个线程做了这所有的事情,所以感觉没法办。

[ 本帖最后由 zhoubug 于 2008-7-24 20:35 编辑 ]

论坛徽章:
0
17 [报告]
发表于 2008-07-25 09:13 |只看该作者
1. 如果你做的是内部服务. 那就让客户端主动发心跳. 服务器只定时检查客户端是不是丢失心跳就OK了.



很明显,对外开放服务的系统,这种方式是不保险的。

2. 如果你做的是开放平台. 那么就模仿libevent. 给每个连接作一个类时器. 规定每个socket的空闲时间.
    定时器就由select来驱动.


高性能网络用epoll,虽然可以设计成不需要太多定时器,但我认为select 最好不用。

谁给你说的epoll没法超时返回?
首先你思路混乱阿伙计。
给你说下apache 的keepalvie的实现,在客户端keep-alvie的时候,apache需要检测客户端是否超时,和你的需求一样。
首先在你的epoll线程 将你的句柄在epoll_wait的时候设置上超时,如1s,此处就是为了让他超时,超时干嘛尼,就是为了
让它有功夫检测一个存储超时时间项目的队列,这个队列里有客户端句柄和其对应的expire time,到这里你也该想到这个队列的时间应该有人维护,
谁哪?就是你处理用户请求的线程,在那里你可以根据处理情况,重设或者删除队列里对应你的超时项。

这样apache就用一个epoll线程兼职维护了所有的keep-alive连接,这样做也是为了不让这些连接占用较多的工作线程。
这个地方是基本不影响接收连接的。因为你的工作线程参与维护这个队列,所以对这个队列的操作是需要加锁的。

在有超时项目的时候,apache是将该项目从队列删除后,将句柄交给工作线程处理的,这样是尽量避免epoll线程受
影响,也符合设计思路。

上面说的是apache 的实验版epoll mpm的实现。

你的问题似乎是在一个线程做了这所有的事情,所以感觉没法办。

..... 不是非常明白你的意思。将你的句柄在epoll_wait的时候设置上超时,如1s,此处就是为了让他超时???


我还是说一下 我的做法吧

epoll_wait 返回, 这个时候你需要做2件事情,
1 处理epoll_wait返回的有效事件,
2 处理没有返回事件的socket, 处理超时的情况,主动断开连接


那么如何查询没有返回事件的socket呢?

很显然,你在加入到epoll 之前就需要首先将时间点和socket记录下来,加入一个队列X,以便以后遍历检查。

效率呢?
非常低, X 需要加锁的情况,
1  新连接建立
2  断开连接
3  定时检查超时。


再仔细分析一下性能。
epoll 返回回来的结果,是单线程处理还是多线程处理? 每个线程做什么事情?

epoll_wait() ;

返回一个结果集。假设有100个结果

A 方案 是每个线程取一个返回记录处理, 另外一个单独线程处理超时扫描   
b 方案 还是一个线程逐一取了结果进行处理,最后做超时扫描。

很明显A效率高,B方案的效率其实就是个单线程,即使你cpu可以跑的线程数目再多也没办法发挥效率。
但是很明显A方案有可能在队列X争锁的情况出现,效率反而可能低。
所以如果能够让socket 自己超时以结果集返回,那么就不会出现争锁的情况了,也就没有必要保存X队列了,
效率会高很多,所以我希望的是这种方式。


而我开始表述的方式就是在没有队列X的情况下,能否做到我的要求? 很明显没有队列X,就无法扫描。epoll_wait也
只会返回个0 对我们没有帮助

论坛徽章:
0
18 [报告]
发表于 2008-07-25 09:28 |只看该作者
很明显,如果你一个线程监听多个socket,是没法通过epoll的超时来完成的.

论坛徽章:
0
19 [报告]
发表于 2008-07-25 09:28 |只看该作者
都是高手啊,学习了

论坛徽章:
0
20 [报告]
发表于 2008-07-25 09:34 |只看该作者
原帖由 yuangong 于 2008-7-25 09:28 发表
很明显,如果你一个线程监听多个socket,是没法通过epoll的超时来完成的.


所以我期望有一个方法,让socket recv 超时的时候,以结果集的方式返回,这样会好很多。当然有更好的思想也可以提。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP