原理:长连接
一、长连接与短连接
短连接:客户端与服务端每进行一次报文收发交易时才进行通讯连接、交易完毕后立即断开连接。
长连接:客户端与服务端先建立连接, 连接建立后不断开,然后在进行报文发送和接收。
二、操作过程
短连接的操作步骤是:
建立连接——数据传输——关闭连接——数据传输——关闭连接
长连接的操作步骤是:
建立连接——数据传输……(保持连接)……(数据传输)——关闭连接
三、优缺点
短连接:
常规的短连接模式下,都是通过不间断刷新请求实现的,比如每间隔3秒发送一次Ajax请求,3秒更新一下数据,然后就这样不间断刷新下去,直到用户关闭网页。
弊端:如果用户很长时间都没有操作,每次刷新都不会返回新数据,这样就造成了资源的浪费,很多请求都是没必要的;用户的输入,跟数据的请求不是同步的,会造成一定的信息延迟。
长连接:
Ajax长连接它的刷新是根据数据来执行的,如果有新数据返回,接收并解析显示数据,然后发起新的Ajax请求,如果一段时间内,用户没有操作,则连接出于睡眠状态,一直等待有用户输入或者请求超时,然后发起下个Ajax请求。
好处:每个信息都会即时推送到客户端,延迟极少;每次请求都是有意义的,比短连接效率高很多。
弊端:一个用户量很多,并且操作非常频繁的网站,长连接模式也会出现过于频繁的刷新问题。目前IE对于HTTP连接数是有限制的,每个网页只能同时进行两个长连接,第三个长连接也会被阻塞。
四、实现长连接原理
长连接需要客户端先向服务器端发送一个请求,服务器端进行不间断的检测,做一个死循环,如果有新数据就推送,如果没有新数据,就一直阻塞。服务器端判断里重要一行代码:usleep(10);就是暂停10毫秒,缓解一下CPU压力。大意就是把前端的循环,搬到了服务器端,减少了网络传输的环节。
五、服务器端优化
如果用长连接,必然会给服务器端造成极大的压力,可以考虑放到memcache中;或者为了减小内存的开销,将聊天记录存到文件里。
六、核心代码
chat.php
<html> <head> <title>聊天室</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="../jquery.min.js"></script> <script> $(function(){ $("#post").click(function(){ var content=$("#content").val(); if(!$.trim(content)){ alert(\'请填写内容\'); return false; } $("#content").val(""); $.post("ajax.php", {content:content});}); }) function getData(msg){ if(msg == undefined) { msg = \'\'; } $.post("get.php",{"msg":msg},function(data){ //var myjson = eval("("+data+")"); if(data){ var chatcontent = \'\'; var obj = eval(\'(\'+data+\')\'); $.each(obj,function(key,val){ chatcontent += "<div class=\'username\'>"+val[\'username\']+" 说:</div>"; chatcontent += "<div class=\'content\'>"+val[\'content\']+"</div>"; }) $("#chatshow").html(chatcontent); } getData(); }) } // function getUser(msg){ // if(msg == undefined){ // msg = \'\'; // } // $.post("getuser.php",{"msg":msg},function(data){ // //var myjson = eval("("+data+")"); // if(data){ // var chatcontent = \'\'; // var obj = eval(\'(\'+data+\')\'); // $.each(obj,function(key,val){ // chatcontent += "<div class=\'username\'>"+val[\'username\']+" 说:</div>"; // chatcontent += "<div class=\'content\'>"+val[\'content\']+"</div>"; // }) // $("#chatshow").html(chatcontent); // } // getData(); // }) // } getData("one"); // $(function(){ // $("#userlist p").click(function(){ // $("#content").val("@"+$(this).text()+" "); // }) // }) // $(function(){ // $(document).keypress(function(e){ // if(e.ctrlKey && e.which == 13 || e.which == 10) { // var content=$("#content").val(); // if(!$.trim(content)){ // alert(\'请填写内容\'); // return false; // } // $("#content").val(""); // $.post("ajax.php", {content:content}); // } // }) // //alert(event.clientX+document.body.clientWidth); // }) /*window.onbeforeunload=function (){ //return("===onbeforeunload==="); if(event.clientX>document.body.clientWidth && event.clientY < 0 || event.altKey){ return("你关闭了浏览器"); }else{ return(document.body.clientWidth); } } */ </script> <style> #chat{margin:0 auto;} #chatshow{width:500px;height:400px;overflow:auto;border:1px solid #ccc;float:left;} #userlist{width:100px;height:400px;overflow:auto;border:1px solid #ccc;float:left;margin-right:2px;} #userlist p{color:#0F0; cursor:pointer;} .clearboth{clear:both;} .username{font-weight:bold;color:#00F;font-size:12px;margin-bottom:3px;margin-top:8px;} </style> </head> <body> <div id="chat"> <div id="userlist"> <div style="font-size:12px;font-weight:bold;">在线用户列表</div> <div class="userlist"> <?php // $dsn = "mysql:host=localhost;dbname=test;charset=utf8\'"; // $db = new PDO($dsn, \'root\', \'root\'); $db = new PDO(\'mysql:dbname=test;host=127.0.0.1;charset=utf8\', \'root\', \'adminroot\'); $rs = $db->prepare("select * from chat where is_login = \'1\'"); $rs->execute(); while($row = $rs->fetch()){ echo \'<p>\'.$row[\'username\'].\'</p>\'; } ?> </div> </div> <div id="chatshow"></div> </div> <div class="clearboth"></div> <div> <textarea name="content" id="content" style="width:600px;height:100px"></textarea> <input type=\'button\' name=\'tj\' id="post" value=\'发布\' > </div> </body> </html>
ajax.php
<?php /*session_start(); $mem = new Memcache; $mem->connect("localhost",11211); if(isset($_POST[\'content\'])){ $con[\'username\'] = $_SESSION["username"]; $con[\'content\'] = $_POST["content"]; $data = $mem->get(\'chat\'); $data[] = $con; $mem->set("chat",$data,0,0); } $mem->close(); */ if(isset($_POST[\'content\'])){ session_start(); $filename = date("Ymd",time()).".txt"; if(file_exists($filename)){ $content = file_get_contents($filename); $data = json_decode($content,true); $con[\'username\'] = $_SESSION["username"]; $con[\'content\'] = $_POST["content"]; $data[] = $con; $file = fopen($filename,"w"); fwrite($file,json_encode($data)); fclose($file); }else{ $file = fopen($filename,"w"); $con[\'username\'] = $_SESSION["username"]; $con[\'content\'] = $_POST["content"]; $data[] = $con; fwrite($file,json_encode($data)); fclose($file); } } ?>
get.php
<?php /*require \'conn.inc\'; function getData(){ $sql="SELECT count(*) FROM `talkroom`"; $res=mysql_query($sql); $count = mysql_fetch_row($res); return $count; } $old = getData(); while(true){ $new = getData(); if($new[0]>$old[0]){ //echo json_encode($new[\'data\']); //print_r($new); echo \'2222222222\'.\'<br/>\'; } //echo \'<br />11111111111111111111111111111111111111111111111111111111111111111111\'; usleep(1000); } */ /*set_time_limit(0); $mem = new Memcache; $mem->connect("localhost",11211); $count = count($mem->get("chat")); $com = true; //$mem->delete(\'chat\'); if($_POST[\'msg\'] == "one"){ exit(json_encode($mem->get("chat"))); } if($_POST[\'msg\'] == "break"){ $com = false; } $time1 = time(); while(true){ if($com){ $data = $mem->get("chat"); if(count($data)>$count){ echo json_encode($data); break; } usleep(300); }else{ break; } } $mem->close();*/ set_time_limit(0); $filename = date("Ymd",time()).".txt"; if(file_exists($filename)){ $content = file_get_contents($filename); $data = json_decode($content,true); $count = count($data); // echo $count;die; if($_POST[\'msg\'] == "one"){ exit(json_encode($data)); } while(true){ $contents = file_get_contents($filename); $datas = json_decode($contents,true); $counts = count($datas); if($counts>$count){ echo json_encode($datas); break; } usleep(300); } }else{ $file = fopen($filename,"w"); $con[\'username\'] = "系统消息"; $con[\'content\'] = "欢迎来到EPGO聊天室"; $data[] = $con; fwrite($file,json_encode($data)); fclose($file); exit(json_encode($data)); } ?>
以上就是这次的全部内容!