聂永的博客

记录工作/学习的点点滴滴。

c_socket.io_server笔记之长轮询超时(timeout)处理

不吐不快

当你习惯了现有WEB服务器,诸如nginx、apache,JAVA应用服务器Tomcat等,你就不能不注意HTTP请求的响应超时时间,需要小心,尤其是反向代理时。当你可以自由控制请求timeout超时时,那是怎样一个快意。
在libev中使用timeout,没有像java那样封装的完善,一切都很原始,但确实锋利多了。

长轮询

一般长轮询需要定义超时时间,一旦超时,服务器端会主动断开连接。无论是xhr形式的长轮询,还是jsonp长轮询,在服务器端处理没有多大差别,输出数据有异。

输出头部

一般优先输出头部,告诉浏览器,需要保持长连接,当然,这需要浏览器支持http 1.1协议,并且明确的注明当前连接为一直保持着:keep-alive:

char heaer_str[200= "";
strcat(heaer_str, 
"HTTP/1.1 200 OK\r\n");
strcat(heaer_str, 
"Content-Type: text/plain; charset=UTF-8\r\n");
strcat(heaer_str, 
"Connection: keep-alive\r\n");
strcat(heaer_str, 
"\r\n");
write_msg(client, heaer_str);

定时器启动,等待

连接什么时候关闭,需要在代码中手动控制,除非浏览器端在发出请求等待响应期间出现异常,无故断开了连接。设服务器端设定好连接持续时间为30秒,那么就应该启动一个定时器,除非所使用的语言层面提供了内置支持。

client->timeout.data = client;
ev_timer_init(
&client->timeout, timeout_cb, 30.00); //30s
ev_timer_start(loop, &client->timeout);

定时器start之后,触发的函数timeout_cb:

 1     static void timeout_cb(EV_P_ struct ev_timer *timer, int revents) {
 2         if (EV_ERROR & revents) {
 3             fprintf(stderr, "error event in timer_beat\n");
 4             return ;
 5         }
 6     
 7         if (timer == NULL) {
 8             fprintf(stderr, "the timer is NULL now !\n");
 9             return;
10         }
11     
12         client_t *client = timer->data;
13     
14         if (client == NULL) {
15             fprintf(stderr, "Timeout the client is NULL !\n");
16             return;
17         }
18     
19         write_msg(client, HTML_RESPONSE_ECHO);
20         free_res(loop, client);
21     }

可以看到,定时器触发之后,本例中将输出一串预先定义好的文字,然后关闭连接。
如何关闭触发器,则很简单:


    ev_timer *timer = &client->timeout;
    
if (timer != NULL && (timer->data != NULL)) {
        ev_timer_stop(loop, timer);
    }

编译运行

编译一下:

gcc longpolling.c -o longpolling ../include/libev.a ../include/http-parser/http_parser.o -lm

运行它:

./long_polling

然后测试:

curl -i http://192.168.190.150:9000/long_polling

可以先看到头部:

HTTP/1.1 200 OK Content-Type: text/plain; charset=UTF-8 Connection: keep-alive

等到30秒后输出具体的文字内容:

The timeout(30s) had passed, you are welcome ~!

小结

所演示的长轮询,没有什么难度,HTTP 1.1头部输出,定时器启动,然后等待输出。
libev内含的timer组件简单易用,控制方便,但不算是最佳实践,官方文档给出了若干种最佳实践方式。具体可参阅:
http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#codeevtimercoderelativeandopti

完整代码

posted on 2013-03-27 08:57 nieyong 阅读(4084) 评论(0)  编辑  收藏 所属分类: socket.io


只有注册用户登录后才能发表评论。


网站导航:
 

公告

所有文章皆为原创,若转载请标明出处,谢谢~

新浪微博,欢迎关注:

导航

<2013年3月>
242526272812
3456789
10111213141516
17181920212223
24252627282930
31123456

统计

常用链接

留言簿(58)

随笔分类(130)

随笔档案(151)

个人收藏

最新随笔

搜索

最新评论

阅读排行榜

评论排行榜