ExtJs+php学习长连接comet技术开端。
传统AJAX技术JavaScript 调用 XMLHttpRequest 对象发出 HTTP 请求,JavaScript 响应处理函数根据服务器返回的信息对 HTML 页面的显示进行更新。
使用 AJAX 实现“服务器推”与传统的 AJAX 应用不同之处在于:
[*]服务器端会阻塞请求直到有数据传递或超时才返回。
[*]客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
[*]当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取。
以上来自IDM DW
理解起来可能很费劲,我做了一下总结,相对比较容易理解。
做了一个简单的及时通讯程序,总结一下各方面。
首先我选用的是ExtJs框架,这个框架无所谓,什么框架都行,但是你要知道你用框架干什么了,其实很简单,就是实现ajax交互,用ajax想后台发送请求。
那么怎么做到长连接:
传统的轮询:
首先客户端定时向服务器发送请求询问服务器有没有新消息,服务器得到新消息之后马上返回消息。
客户端得到消息,刷新(注意不是全页面刷新,而是ajax动态写入HTML元素让页面局部刷新(ajax=页面局部刷新技术))
上面的方法打个比方就是你定时让一个人去考察市场,然后考察完毕马上回来,你来做相应的处理。结果是你不能在市场发生变更的第一时间得到市场消息。
长连接方式:
页面加载的时候向服务器发送请求,询问是否有新消息。
服务器查询最新消息,进行判断:
如果有新消息,发送到客户端。
如果没有最新消息,阻塞连接。
页面得到消息之后刷新到页面,然后马上继续与服务器建立连接(长连接更应该说是与服务器建立连接)。
这个方法就好像,你安排一个人在市场,让他在市场发生变化的时候马上回来通知你,然后马上回去继续考察。
下面是我用Ext+PHP自己做的例子,算是一个入门。
Ext版本:4.0
定义类ChatWin
1 Ext.define('Leaves.im.ChatWin', {
2 extend : 'Ext.window.Window',
3 timestamp : 0,
4 mainWindow : null,
5
6 initComponent : function() {
7 this.createWindow(this);
8 },
9
10 createWindow : function(me) {
11 me.display = Ext.create('Ext.container.Container', {
12 width : '100%',
13 height : 200,
14 html:''
15 });
16
17 var editor = Ext.create('Ext.form.field.HtmlEditor', {
18 xtype : 'htmleditor',
19 enableColors : false,
20 enableAlignments : false,
21 width : '100%'
22 });
23
24 var mainPanel = Ext.create('Ext.panel.Panel', {
25 frame : true,
26 height : '100%',
27 width : '100%',
28 layout : 'vbox',
29 items : [ me.display, editor ],
30 buttons : [ {
31 text : '发送',
32 handler : function() {
33 me.sendMessage(editor.getValue());
34 editor.setValue();
35 editor.focus();
36 }
37 } ]
38 });
39
40 me.mainWindow = Ext.create('Ext.window.Window', {
41 title : '聊天室',
42 height : 500,
43 width : 600,
44 layout : 'fit',
45 items : [ mainPanel ]
46 });
47 },
48
49 /**
50 * 获取消息 timestamp 最后一次获取消息时间
51 */
52 getMessage : function(timestamp) {
53 var me = this;
54 Ext.Ajax.request({
55 url : 'comet.php',
56 success : function(response) {
57 var text = response.responseText;
58 var jsonObj = Ext.JSON.decode(text);
59
60 me.display.update(me.display.html+jsonObj.msg+'<br/>',true);
61
62
63 timestamp = jsonObj.timestamp;
64 me.getMessage(jsonObj.timestamp);
65 },
66 failure : function(response) {
67 var text = response.responseText;
68 var jsonObj = Ext.JSON.decode(text);
69 me.getMessage(jsonObj.timestamp);
70 },
71 params : {
72 timestamp : timestamp
73 }
74 });
75 },
76 /**
77 * 发送消息 message 要发送的消息
78 */
79 sendMessage : function(message) {
80 Ext.Ajax.request({
81 url : 'comet.php',
82 params : {
83 msg : message
84 }
85 });
86 },
87
88 showChatWin : function(y, x, title) {
89 this.mainWindow.title = title;
90 this.mainWindow.y = y;
91 this.mainWindow.x = x;
92 this.getMessage(this.timestamp);
93 this.mainWindow.show();
94 }
95 }, function() {
96 Ext.Ajax.timeout = 900000;
97 });
启动类comet.js
1 Ext.Loader.setConfig({
2 enabled : true,
3 paths : {
4 'Leaves.im.ChatWin' : 'ChatWin.js'
5 }
6 });
7 Ext.onReady(function() {
8 var charWin = Ext.create('Leaves.im.ChatWin');
9 charWin.showChatWin(100,100,'我的聊天框');
10 });
主页面
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>Comet demo</title>
6 <link href="../ExtJs/resources/css/ext-all.css" rel="stylesheet"
7 type="text/css">
8 <script type="text/javascript" src="../ExtJs/ext-all-debug.js"></script>
9 <script type="text/javascript" src="comet.js"></script>
10 </head>
11 <body>
12
13 </body>
14 </html>
服务器PHP脚本
1 <?php
2 $filename = dirname ( __FILE__ ) . '/data.txt';
3 $msg = isset ( $_POST ['msg'] ) ? $_POST ['msg'] : '';
4
5 if ($msg != '') {
6 file_put_contents ( $filename, $msg );
7 die ();
8 }
9
10 set_time_limit ( 0 );
11 $lastmodif = isset ( $_POST ['timestamp'] ) ? $_POST ['timestamp'] : 0;
12 // 取得文件最后修改时间
13 $currentmodif = filemtime ( $filename );
14
15 while ( $currentmodif <= $lastmodif ) {
16 // 有释放CPU占用率的作用
17 usleep ( 100000 );
18 // 清除文件缓存信息
19 clearstatcache ();
20 $currentmodif = filemtime ( $filename );
21 }
22
23 $response = array ();
24 $response ['msg'] = file_get_contents ( $filename );
25 $response ['timestamp'] = $currentmodif;
26 echo json_encode ( $response );
27 ob_flush ();
28 flush ();
29 ?>
页:
[1]