原理:長連接
一、長連接與短連接
短連接:客戶端與服務端每進行一次報文收發交易時才進行通訊連接、交易完畢后立即斷開連接。
長連接:客戶端與服務端先建立連接, 連接建立后不斷開,然后在進行報文發送和接收。
二、操作過程
短連接的操作步驟是:
建立連接——數據傳輸——關閉連接——數據傳輸——關閉連接
長連接的操作步驟是:
建立連接——數據傳輸……(保持連接)……(數據傳輸)——關閉連接
三、優缺點
短連接:
常規的短連接模式下,都是通過不間斷刷新請求實現的,比如每間隔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)); } ?>
以上就是這次的全部內容!