精华内容
下载资源
问答
  • 提交varinput=document.getElementsByTagName('input')[0]varul=document.getElementsByTagName('ul')[0]functionsubmit(){varli=document.createElement('li');if(input.value!=''){li.innerHTM...

    摘要:html>

    提交

    var input = document.getElementsByTagName('input')[0]

    var ul = document.getElementsByTagName('ul')[0]

    function submit(){

    var li = document.createElement('li');

    if(input.value!=''){

    li.innerHTML = input.value;   //向新元素中添加内容  内容为input框的值

    ul.appendChild(li);   //将元素添加到列表中

    input.value = '';

    }else{

    alert('请在输入框输入信息');

    input.focus();

    }

    }

    1.获取到元素input框和元素button

    2.给button绑定点击事件,点击提交按钮后创建一个新元素li,将input框的值添加到li中

    3.将元素li添加到ul列表中

    4.将input框的值清空

    批改老师:欧阳批改时间:2019-01-09 16:41:01

    老师总结:写的不错,就是代码有点少,加点样式,页面会更好看。加油。

    展开全文
  • 网页客户聊天系统源码,一句话简介:只需要1个静态HTML的页面就能互相聊天。...相关原理和教程: https://blog.csdn.net/sb11011bs/article/details/112133845 QQ 773179801 任何问题请与我联系。
  • AJAX 聊天实现原理终极解析 闲来无事,做了一个AJAX聊天室,以前一直想做一个,因为我和几个朋友是Linux机子,尽管我们的机子上都有apache服务器,但要发送一个信息却不是很容易,老是要借助客户端,有时候吧...

    AJAX 聊天室实现原理终极解析
    闲来无事,做了一个AJAX聊天室,以前一直想做一个,因为我和几个朋友是Linux机子,尽管我们的机子上都有apache服务器,但要发送一个信息却不是很容易,老是要借助客户端,有时候吧Linux下的qq和gtalk之类的聊天软件太麻烦,所以呢,就写了一个聊天室。
    先说一下我实现的这个聊天室的聊天模式:
        1,无须注册,登录之类,打开页面就可以聊天。
        2,为避免过量冗余信息,客户端只获取在一定时间以后发送的信息,比如10秒内。
        3,可以单对单聊天,仅限于一个对一个,如果想一对多同时聊天,那么就必须要注册登录才能解决。
    这样就简化了一些聊天的模式了,如果想要实现例如qq,msn,gtalk之类的聊天模式,就必须要用到用户注册登录,这样一来,先有的很多ajax聊天程序都已经设计的很完美了,例如:
    http://blog.jwchat.org/jwchat/
    http://ajaxbber.sourceforge.net/index.php?page=home    
    还有很多,不一一列举。
    分析一下原理:
    客户端必须不断的刷新,向服务器获取信息和在线会员列表。我采用session验证,因为session够安全,但是在线会员是存入数据库的,因为如果在线会员比较多,存入数据库,远比用原来的session直接以文件形式存储的要快。session存入数据库,有专门讲解的,为了简化,这里只用到 session_id 这个session_id其实在服务器端还是以文件形式存储的,先做两个表:
    message( id , status, nick, to_uid, to_sid, to_ip, from_uid,from_sid,from_ip , message)
    online(uid, sid, ip ,nick, message_id , lastupdate, tip , status , link_uid , link_sid, link_ip )
    如果不实现单聊,表就可以简化为:
    message( id , nick, from_uid,from_sid , from_ip , message) ,
    online(uid, sid, ip ,nick, message_id , lastupdate, tip )
    为了简化,分单独几道ajax请求和服务器通信:
    1.获取信息,这个请求负责刷新获取信息,在线用户。    chat.php?ac=get
    2.发送信息,这个请求负责向服务器发送信息。             chat.php?ac=send   
    3.请求连接,这个地方负责实现单聊连接的。            chat.php?ac=linkto
    4.处理连接,处理接收或拒绝单聊请求。            chat.php?ac=cut

    先来分析第一个发送请求,获取消息和在线会员。
    客户端向服务器发出请求后,这里我采用这样的提交形式:chat.php?ac=get
    先判断用户是否存在?
    session_start();
    $sid = session_id();
    $ip   = $_SERVER['REMOTE_ADDR'];
    $dateline = time();
    // 获取用户当前设置的昵称。
    $nick=$_POST['nick']; // 如果你的ajax请求是get实现的,那么这里就改动一下。
    $sql="SELECT * FROM online WHERE sid='$sid' AND ip='$ip' LIMIT 1 " ;
    第一步就是要判断用户是否已经存在数据表中,没有,则表示是第一次登录,需要新建立一个用户。
    这里同时采用了 sid 和 ip 来验证用户是否已经在表中存在,用ip主要是为了防止session被劫持。但如果是内网劫持,因为网关出口ip通常是一个,所以这一招基本没太大用处,可以不用判断ip,后来发现我这里其实是自找麻烦,因为有的公司的ip是不断变化的,我一个朋友的公司ip就是在两个直接随机切换,所以建议还是只判断 sid就可以了,毕竟劫持session_id的可能性还是比较小的。
    如果用户不存在,那么新插入一条数据就可以了。
    如果用户存在,先刷新用户的最后更新时间,
    $sql="UPDATE online SET nick='$nick',dateline='$dateline' WHERE sid='$sid' AND ip='$ip' LIMIT 1 ";
    然后删除已经离线的用户:
    $interval = 10 ; // 十秒没用刷新的话,就认为其已经离线了。
    $sql="DELETE FROM online WHERE dateline < $dateline - $interval ";
    获取在线会员
    $sql="SELECT * FROM online WHERE 1 ";
    获取用户自己:
    $sql="SELECT * FROM online WHERE sid='$sid' ";
    存入变量$user中。
    获取信息。
    $message_id=$user['message_id']  ?  $user['message_id']  : 0;
     // 这个$user变量就是我们前面获取的当前用户。
    $sql="SELECT * FROM message WHERE dateline > $dateline-$interval AND id > $message_id AND from_sid != '$sid' AND status=1 ORDER BY dateline ASC";
    解释一下,这里只获取当前时间-10以后的信息,那么以前的信息就不会获取了,也就是说不会像qq那样,即使你离线了,别人发给你的信息,在你下次登录后还能获取到。因为我们没用会员注册,所有的信息都是无定向的。
    这里用 status=1表示信息是群聊的, status=0表示信息是单聊的。所以如果只想实现群聊,不想实现单聊的,就不用判断状态了。
    在获取信息的同时需要更新用户的message_id,这个标志用来表示当前用户已经获取到哪条信息的位置了,如果没用这个标志,那么,每次刷新,用户上次获取过的信息,如果在10秒内,这次还会获取到,假设有人连续发送信息,那么客户端会获取到大量重复信息,当然,客户端可以用一个隐藏的文本框来存储当前用户已经获取到哪条信息了,这个方法既笨拙,又不实用,而且我好像见到有人就是这么做的。

    while($row=mysql_fetch_array(mysql_query($sql)) ){
        $message_id = $row['id'] > $message_id  ? $row['id'] : $message_id  ;
        // 不论您是否采用这样的循环方式获取消息,您都应该把message表的取到的最大id记录下来。
    }
    下面获取单聊的信息。因为单聊的窗口通常会和群聊分开的。
    $sql="SELECT * FROM message WHERE dateline > $dateline-$interval AND id > $message_id AND from_sid != '$sid' AND status=0 AND to_sid='$sid' order by dateline asc";
    好下面在获取完单聊消息后,仍然需要执行:
    $message_id = $row['id'] > $message_id  ? $row['id'] : $message_id  ; 
    以获取最大的消息id。

    当然了,如果您觉得麻烦,完全可以这样:
    $maxId_sql="SELECT max(id) FROM message";
    因为我们每次取完消息后,必然会把当前所有的可用信息取完,只是这样做增加了一次数据库查询。
    下面,更新用户表的 message_id;
    $sql="UPDATE online SET message_id='$message_id'  WHERE sid='$sid' AND ip='$ip' LIMIT 1";
    好了,这样下次再取信息的时候,就会由这个message_id向后开始取,只取 id 比message_id大的信息。

    吐出的最终数据最好是JSON格式的,这样也好减少流量,方便处理文本。
    您总不希望别人发送给您信息的时候,发给你这样一个:<script> location.href="g.cn" ;</script>
    这样你的页面啪的一声就转到google的主页了!
    所以在前台处理的时候需要把将要提交的信息进行转义:
    str.replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/'/g,'&#039;').replace(/"/g,'&quot;');
    在php端处理的时候就比较轻松了:htmlspecialchars( $_POST['msg'] );
    好了,信息算是处理完成了,然后只要吐出就可以了:
    header('Content-Type:text/html ; charset=UTF-8'); // 设定你的编码。
    按照某些w3c mime标准来说,json吐出的格式应该是:application/json;
    当然不推荐这么做,只需吐出 text,或html就可以了,这样做是方便调试。
    我们在后台把所有取出的信息组合成一个大的数组:
    $echo_json=array();
    $echo_json['msg']=$msg ; // 取出的消息
    $echo_json['online']=$online; // 取出的用户
    echo json_encode( $echo_json );
    当然,为了节约流量,最好把吐出的字母变量缩短,我就是这么干的。一个字母足够了。


    2。发送信息。
        $msg_status =   1;  // 信息状态,1表示群,0表示私聊
        $toip        =   $user['link_ip'];      // 发送的目标对象信息直接由用户的表里取,如果没有单聊,省去。
        $touid         =   $user['link_uid'];
        $tosid          =   $user['link_sid'];
        $nick           =   htmlspecialchars($_POST['nick']);    // 这个是用户发送消息时的昵称。
        $message        =   htmlspecialchars($_POST['message']); // 消息体。
        $sql="INSERT INTO message(status,from_uid,from_sid,from_ip,to_uid,to_sid,to_ip,nick,dateline,message) VALUES('$msg_status','$uid','$sid','$ip','$touid','$tosid','$toip','$nick','$dateline','$message')";
        插入消息体,如果有单聊的话,需要加上判断:
        $sql="SELECT * FROM online WHERE sid='$link_sid' AND ip='$link_ip' LIMIT 1";
        而如果不存在    $user2,单聊的对象,那么,返回失败消息,提示用户发送消息已失败,对象已断开。
        好,吐出消息:
        这里可用简化一下处理结果,如果发送消息成功了,那么什么也不返回,如果失败了返回0.
        这样做为了省流量。因为毕竟发送消息成功的时候比较多,失败比较少。在客户端用js取出返回的数据
        判断是否为空,为空,则,发送成功,不为空,则发送失败。
        echo $result;

    3。单聊请求,如果不提供单聊,3,4两条可用略过了。
    这里采用的是,向服务器发送连接请求,然后由对方选择是否接纳。
    当然如果不想让用户自己选择连接某个对象,而是由服务器自动配对,这就是当今很流行的路过聊天方式。
    其实原理非常简单,例如 luguode.com ,等等,这类聊天非常的多。
    简要说明一下由服务器自动配对的做法:
    第一步:获取哪些用户仍是单身:
    先说明一下状态代码表示:
    online表中的status 字段:为0表示用户单身,为3表示用户已经配对。1,2留着有其他用处。
    $sql="SELECT * FROM online WHERE sid !='$sid' AND status=0 ";
    假如我们取出一个数组:$single_onlines;
    下面我们取出一个随机的用户:
    srand((double)microtime()*1000000);
    // 初始化随机数种子,php 4以后版本据说已不在需要,
    // 但很多时候,我还是需要这句才能得到正确的随机数,shit!
    $target_index    =    rand( 0 , count($single_onlines)-1) ; //随机下标
    $target_sid    =     $single_onlines[$target_index]['sid'] ;
    $target_ip        =      $single_onlines[$target_index]['ip'] ;
    // 获取到目标的sid 了,下面同时更新用户和我!
    $sql="UPDATE online SET status='3', link_sid='$target_sid', link_ip='$target_ip' WHERE sid='$sid' AND ip='$ip' LIMIT 1 ";// 更新我的状态

    $sql="UPDATE online SET status='3', link_sid='$sid', link_ip='$ip' WHERE sid='$target_sid' AND ip='$target_ip' LIMIT 1 "; // 更新目标状态

    当然了,在更新前,需要做一些简要的判断,例如,我自己是不是已经是3了阿,是表示我已经是和别人建立单聊了,那么就返回一个错误了。

    说到这类不知道您发现问题了没?就是,当我没有请求和别人单聊的时候,也可能会被别人啪的连上了。
    简单解释一下:例如现在有三个人 A,B,C,我是A,这三个人都是单身,当我向服务器发出请求连接的时候,
    这个时候,服务器随机找出了B,而B这个时候并没有向服务器发出连接请求,也会被啪连上了。
    所以我们就可以加一个状态判断。例如:status=1表示用户正在向服务器发出连接请求。
    0,表示用户什么也没有做,也不想和别人单聊。
    而这个时候,就从那些状态为1的用户里面找出一些,随机连接。
    如果没有单身了,那么先把用户状态更新为1,返回没有找到的提示。

    感觉很罗嗦。所以我就自己设计了一个连接--服务器处理--客户端处理--的这样一个模式。
    请求地址:chat.php?ac=linkto
    post来的变量:
    $linkto=$_POST['linkto'];// 表示要和哪个uid的用户建立连接
    如果用户是单身状态,那么连接请求可用,用户的在线列表左边将会出现一个--连接的按钮
    这个时候,uid就派上用场了,为什么不用session_id?因为你不可能把用户的session_id都发送给
    客户端吧?只有发送uid了,
    这个uid可用是随机字母,也可用是随机数字,我这里采用的是6为随机数字。
    这里要稍微改动一下,用户第一次访问的情况。
        srand((double)microtime()*1000000);
        $uid=rand(100000,999999);
        $sql="SELECT uid FROM online WHERE uid='$uid'";
        while( mysql_fetch_array( mysql_query($sql) )){
            $uid=rand(100000,999999);
        }// 直到产生一个唯一的uid为止.
        循环来验证当前产生的uid是否已经在表中存在了?如果存在,那么继续产生,如果不存在,那就用这个了。
        定义一下状态:
        0:用户单身
        1:用户正在发出连接请求。
        2:用户正在被连接请求。
        3:用户已经配对。
    当连接请求发出的时候,需要判断这样几种情况?
        自己状态是:
        status=1,
           我已经在请求了,这个时候可用根据需要是否允许用户进行多次请求。
           一般是允许的。因为如果不允许的话,你发送过去,对方没有即使处理,那么就要一直挂着等了。这样显然不好。当然也可以这么做了。
        status=2:
           我在被请求,提示错误
        status=3:已经成对,提示错误。
       
        第二步,查询对象是否存在,或已经掉线?
            $sql=SELECT * FROM online WHERE uid='$linkto' LIMIT 1;
            $user2=mysql_fetch_array(mysql_query($sql));
            如果不存在$user2,证明已经掉线,返回错误信息。
            否则进入下一步:
        目标状态:
        status=0或1
            更新目标用户,返回发送请求成功。
            $sql="UPDATE online SET link_uid='$uid2' AND link_sid='$sid2' AND link_ip='$ip2' ";
        status=2,
            目标已经有人请求,返回请求错误信息。
        status=3,目标已经成对,返回错误信息
       
    4.处理连接:
        每次刷新信息时候,返回用户自己的信息:
        在客户端,用js检测用户状态信息是否为2?
        如果为2,则弹出对话框,提示用户是否接收或拒绝连接请求。
        接收的时候,仍需要注意几种情况:
        自己的状态判断,和目标的状态判断。   

    最后需要增加一个刷新用户状态,
    if($user['status']==3){ // 刷新单点连接
        $linksid=$user['linksid'];
        $linkip=$user['linkip'];
        $sql="SELECT uid FROM online WHERE sid='$linksid' AND ip='$linkip' LIMIT 1";
        if(!mysql_fetch_array( mysql_query($sql) ) ){
           $sql="UPDATE online SET status='0',info='$info',linkuid='',linksid='',linkip='' WHERE sid='$sid' AND ip='$ip' LIMIT 1";
           //更新用户状态,使其重新变为0。
        }
    }

    然后还需要提供一个手动断开连接的处理,这就比较简单啦,直接把自己的状态,和对方状态更新为0,同时清楚掉link_uid....之类的

    下面说说前台,基于JQuery的!
    前台比较简单。
    Chat={};
    Chat.get=function(){
        $.post('chat.php?ac=get',{'nick':$('#nick').val()},function(data){
              // 这里把取到数据 data对象里面的消息追加到聊天窗口。
              $.each(data.msg,function(i,msg){
                  //比较简单就不多写了。
              });
              //scroll('im'); 这里加一个滚动效果,可用把窗口自动滚动到最底部。
          }
            setTimeout('Chat.get()',3000);
        },'json');
    }

    function scroll(id){
             var scrollTop=document.getElementById(id).scrollHeight - document.getElementById(id).clientHeight >= 0 ? document.getElementById(id).scrollHeight - document.getElementById(id).clientHeight : 0;
             document.getElementById(id).scrollTop=scrollTop;
     }

    其他的请求就略过了,因为比较简单。原理都差不多了。
    好了,到这里就基本讲解完了一个ajax聊天室的原理,如果是注册聊天,实行起来会比这个容易些!

    展开全文
  • 基于WWW的ASP聊天实现原理.pdf
  • 目标servlet、jsp实现简单聊天室,用户通过浏览器登录后进入聊天室,可发送消息进行群聊,点击聊天信息框中的用户名可实现拍一拍功能。基础知识数据的存取 setAttribute / getAttributerequest请求对象 :有效时间短...

    目标

    servlet、jsp实现简单聊天室,用户通过浏览器登录后进入聊天室,可发送消息进行群聊,点击聊天信息框中的用户名可实现拍一拍功能。

    基础知识

    数据的存取 setAttribute / getAttribute

    request请求对象 :有效时间短

    ServletContext上下文对象:一直存在于服务器,存储公有、 共享数据

    Session会话对象:独立

    网站默认页面一般是index.jsp

    实现思路

    1.登录页面 login.jsp 输入昵称

    2.编写一个LoginSevlet,处理登录提交的昵称,保存登录昵称到session(会话变量)

    若昵称合法 if(nickname.length()!=0),跳转到聊天室,不合法回到登录页面

    3.编写聊天室页面chatroom.jsp ,是一个框架,把多个页面集成到一个页面中

    4.聊天内容显示message.jsp,不断自动刷新标签内设置响应头,用${上下文变量}显示聊天内容

    5.input.jsp(不刷新)输入聊天内容文本框text,点击发送聊天内容按钮时,将把文本框的聊天信息提交给ChatServlet处理。下方有超链接可退出聊天室。

    退出聊天室

    6.ChatServlet:检测聊天信息合法性,把聊天信息加入到ServletContext变量(字符串)中,(每次都将xx:xxxx加入上下文字符串)

    判断是否存在该变量,存在则直接读取现有聊天内容,把数据加入进去后,重新写回上下文变量

    7.实现拍一拍功能(目的:学习如何进行链接操作)

    每个人名做成一个链接,访问某一个servlet,该servlet可以在聊天信息(上下文变量)里添加一行,xx拍了yyy一下,跳转回message.jsp

    问题:链接里应该包含yyy参数,servlet?nick=yyy

    say = ""+nickname+""+":"+text;

    8.多人聊天实现:多种类型浏览器

    关键代码

    login.jsp

    昵称:

    input.jsp

    退出聊天室

    message.jsp

    一起来聊天吧

    ${says}

    LoginServlet.java

    package chatting;

    import javax.servlet.RequestDispatcher;

    import javax.servlet.ServletException;

    import javax.servlet.annotation.WebServlet;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import javax.servlet.http.HttpSession;

    import java.io.IOException;

    import java.io.PrintWriter;

    @WebServlet(name = "LoginServlet2",urlPatterns = {"/login.do"})

    public class LoginServlet2 extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    //避免乱码

    response.setContentType("text/html;charset=utf-8");

    request.setCharacterEncoding("utf-8");

    //nickname保存用户昵称

    String nickname = request.getParameter("nickname");

    //nickname存储到session变量中

    HttpSession session = request.getSession();

    session.setAttribute("nickname",nickname);

    //对nickname进行合法性判断

    if(nickname.length()!=0){

    //昵称合法,则进入聊天室页面

    request.getRequestDispatcher("/chatroom.jsp").forward(request,response);

    }

    else{

    //昵称不合法,返回登陆页面

    request.getRequestDispatcher("/login.jsp").forward(request,response);

    }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    }

    ChatServlet.java

    package chatting;

    import javax.servlet.RequestDispatcher;

    import javax.servlet.ServletContext;

    import javax.servlet.ServletException;

    import javax.servlet.annotation.WebServlet;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import javax.servlet.http.HttpSession;

    import java.io.IOException;

    import java.util.Vector;

    @WebServlet(name = "ChatServlet",urlPatterns = "/input.do")

    public class ChatServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    //防止乱码

    request.setCharacterEncoding("utf-8");

    response.setContentType("text/html;charset=utf-8");

    HttpSession session = request.getSession();

    String text = request.getParameter("text");

    //text存储聊天信息,并进行合法性判断

    if (text.length()!=0) {

    String say =new String();

    //获取session中的昵称

    String nickname = (String)session.getAttribute("nickname");

    //将昵称作为链接,并传参

    say = ""+nickname+""+":"+text;

    String says = new String();

    //将昵称和聊天信息一起放在上下文变量

    ServletContext context = getServletContext();

    if(context.getAttribute("says")!=null){

    says = context.getAttribute("says") + say + "
    ";

    }

    else{

    says = say + "
    ";

    }

    context.setAttribute("says", says);

    request.setAttribute("says", says);

    }

    //转发

    RequestDispatcher dispatcher = request.getRequestDispatcher("/input.jsp");

    dispatcher.forward(request, response);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    }

    NickServlet.java

    package chatting;

    import javax.servlet.RequestDispatcher;

    import javax.servlet.ServletContext;

    import javax.servlet.ServletException;

    import javax.servlet.annotation.WebServlet;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import javax.servlet.http.HttpSession;

    import java.io.IOException;

    import java.io.PrintWriter;

    @WebServlet(name = "NickServlet",urlPatterns = "/NickServlet")

    public class NickServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    response.setContentType("text/html;charset=UTF-8");

    request.setCharacterEncoding("utf-8");

    //将拍一拍放到上下文变量says中 一起输出

    HttpSession session = request.getSession();

    //nickname存储当前用户昵称

    String nickname = (String)session.getAttribute("nickname");

    //name存储连接中传递的参数,即被拍的用户昵称

    String name = java.net.URLDecoder.decode(request.getParameter("nickname"),"UTF-8");

    String pick = nickname+"拍了拍"+name+"
    ";

    ServletContext context = request.getServletContext();

    String says = context.getAttribute("says")+pick;

    context.setAttribute("says",says);

    RequestDispatcher dispatcher = request.getRequestDispatcher("/chatroom.jsp");

    dispatcher.forward(request, response);

    }

    }

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

    展开全文
  • 基于Socket的聊天实现原理 福建泉州数据通信局 林天山(lts@www.gz.fj.cn) ---- Socket聊天室基本原理是,抛开OGI和WWW服务器,根据HTML规范,接收到浏览器的请求以后,模仿WWW服务器的响应,将聊天内容发回...
     marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280">

    基于Socket的聊天室实现原理

    福建泉州数据通信局 林天山
    (lts@www.gz.fj.cn)


    ---- Socket聊天室基本原理是,抛开OGI和WWW服务器,根据HTML规范,接收到浏览器的请求以后,模仿WWW服务器的响应,将聊天内容发回浏览器。在浏览器看来就像浏览一个巨大的页面一样始终处于页面联接状态, 这就是一个专门的聊天服务器,一个简化了的WWW服务器。

    ----这样相比CGI方式来说,Socket聊天室的优点就很明显:

    1. 不需要专门的WWW服务器,在聊天服务器里完成必要的工作,避开耗时的CGI 过程。
    2. 如果使用单进程服务器,就不需要每次产生新进程。
    3. 数据交换完全在内存中进行,不用读写文件。
    4. 不需要定时刷新,减少屏幕的闪烁,减少对服务器的请求次数。

    ----下面我们来看看具体实现流程。

    一、 聊天服务器实现流程

    ----下图是服务器程序流程:

    0287500.jpg

    ----上图中的“处理用户输入”部分可以细化为下图:

    0287501.jpg

    ----用户数据输入都是通过URL传送,下面是几个URL实例,结合后面客户端流程,可以更好地理解系统结构。

    ----这是一个用户名密码均为‘aaa'的聊天用户登录系统,说了一句话“hello”,然后退出所产生的一系列请求,其中密码用系统函数crypt加密过:

        /login?name=aaa&passwd=PjHIIEleipsEE    /chat?sid=ZUyPHh3TWhENKsICnjOv&passwd=PjHIIEleipsEE    /talk?sid=ZUyPHh3TWhENKsICnjOv&passwd=PjHIIEleipsEE    /names?sid=ZUyPHh3TWhENKsICnjOv/doTalk?sid=ZUyPHh3TWhENKsICnjOv &passwd=PjHIIEleipsEE&message=hello    /leave?sid=ZUyPHh3TWhENKsICnjOv&passwd=PjHIIEleipsEE

    二、 客户端具体登录过程

    ---- 我们先看看聊天界面:

    0287502.jpg

    ----聊天界面由三个frame组成,其中chat帧是聊天内容显示部分,talk帧是用户输入部分,包括聊天内容输入、动作、过滤以及管理功能都在这一帧输入,names是在线名单显示部分,这一部分是定时刷新的。

    ---- 让我们从浏览器的角度来看看进入聊天室的过程。

    ---- 1.首先浏览器请求页面:
    ---- http://host:9148/login?name=NAME&passwd=PWD

    ---- 此时产生了一个连接到服务器聊天端口的Socket联接,并发送了一行数据:
    ---- GET /login?name=NAME&passwd=PWD HTTP/1.1

    ----2.服务器生成一个session ID,验证密码以后,发回:

        HTTP/1.1 200 OK    <其他头信息>    Content-TYPE: text/html    <空行>        ……    ……    

    ----然后服务器关闭Socket联接。

    ----3.浏览器收到以上html文件后,将会依次打开三个联接(其中的$sid和$encrypt_pass是变量):

        /chat?sid=$sid&passwd=$encrypt_pass     /talk?sid=$sid&passwd=$encrypt_pass     /names?sid=$sid

    ----这三个联接中的第一个联接chat在整个聊天过程中都是保持联接的,这样从浏览器角度来看,就是一个始终下载不完的大页面,显示效果上就是聊天内容不是靠刷新来更新,而是不断地向上滚动。通过察看html代码可以看到,只有< html >< body >,然后就是不断增加的聊天内容,没有< /body >< /html >。

    ---- 另外两个联接在页面发送完毕以后,Socket就关闭了。

    ---- 这样一次登录聊天室实际上有四次Socket联接,但登录完成以后,只有chat帧的Socket是保持联接的,用于接收来自服务器的聊天信息,这是 Socket聊天室的关键所在。

    ----在服务器端储存了所有参加聊天的客户的chat Socket,当有人发言时,服务器就向所有chat Socket发送聊天内容。

    ---- Talk与names帧的html实际上和普通的form是一样的。

    ---- 4.在用户登录以后,服务器端保存了一张包括用户信息的表格:

    ---- 在perl实现中,我们使用哈希结构储存信息,以session ID 作为key索引。这样的存储结构便于存取数据,回收空间。每个客户信息是一个数组:

        [socket,name,passwd,privilige,filter,login_time,color]    socket:储存chat帧socket联接    name:用户名    passwd:密码    privilige:权限    filter:某个用户的过滤列表的引用(reference)    login_time:记录登录时间,以便以后清除一些超时联接    color:用户聊天颜色

    ----以上用户数据大部分是在login阶段,用户通过密码验证以后填入的。只有chat Socket要等到chat帧显示以后才得到。如果超过一定时间,Socket 还是没有填入,说明浏览器取得主框架以后连接中断了,这时候就需要删除该用户数据。

    ---- 以上是聊天室核心部分,其他部分,如用户注册、改密码等可以沿用CGI聊天室代码。

    三、 需要改进的地方

    ---- 目前提供了聊天、悄悄话、动作这些基本聊天功能以及过滤用户名单这样的附加功能。管理功能完成了踢人、查IP、任命室主。今后需要改进的地方有:

    ----稳定性:目前聊天室还没有经过大用户量测试,稳定性还不能充分保证。由于是单进程循环服务器,某个用户通信死锁将导致所有人死锁。如果采用并发多进程服务器,可以使稳定性得到提高。但这样的系统对服务器资源消耗也会大许多。

    ---- 功能:自建聊天室等功能还没有完成,这些外围功能在稳定性有保证以后就可以比较容易地加入。

    <script language=JavaScript> function adbn(sname,pname) {var Jtoday= new Date();jt=Jtoday.getTime();var tilex='';var catex='';var sizex='1x1';var w=1;h=1;var adname='.cn';document.write('
    ');document.write(''+sname+pname+';sz='+sizex+';'+catex+tilex+'ord='+jt+'?');document.write('
    ');}</script><script language=JavaScript>adbn('www.ccw.com.cn/','week');</script>
    week;sz=1x1;ord=998206380988?



    展开全文
  • AJAX聊天实现原理 JQuery+PHP

    万次阅读 热门讨论 2009-05-30 13:31:00
    AJAX 聊天实现原理终极解析闲来无事,做了一个AJAX聊天室,以前一直想做一个,因为我和几个朋友是Linux机子,尽管我们的机子上都有apache服务器,但要发送一个信息却不是很容易,老是要借助客户端,有时候吧Linux...
  • 聊天机器人已经有了很多很好的实现,比如图灵机器人、微软小冰都非常的智能而且语气都与人类相似。但这并不是一件一劳永逸的事情,在特定的场景下问题的回答是有边界的或者符合特定业务场景的,所以还是需要可以按需...
  • 基于socket的聊天室,目前还比较少见,国内比较知名的有网易和碧海银沙聊天室。这种聊天室的特点 很明显,不象CGI聊天室那样不管有没有人发言,都会定时刷新。而是当有人发言时,屏幕上才会出现新聊天内容,而且聊天...
  • Java 聊天室的简单实现原理

    千次阅读 2017-09-09 15:57:40
    简单的JAVA聊天室:一般是使用Socket基于 C/S 架构,其设计的过程如下: 1)服务器通过某个端口监听是否有客户端发送Socket链接请求。 2)客户端向服务器端发送一个Socket链接请求。 3)服务器端调用accept()方法...
  • 简单聊天室采用各种内部对象不适用数据库实现。一个聊天室要实现的基本功能是:1.用户登录进入聊天室,2.用户发言3.用户可以看见别人发言刚才算是简单的需求分析了,现在就应该是进行mvc结构的设计:1.视图,有登陆...
  • AJAX聊天实现原理 JQuery+PHP 【转】

    千次阅读 2011-03-21 13:57:00
    AJAX 聊天实现原理终极解析 闲来无事,做了一个AJAX聊天室,以前一直想做一个,因为我和几个朋友是Linux机子,尽管我们的机 子上都有apache服务器,但要发送一个信息却不是很容易,老是要借助客户端...
  • 用FMS做聊天室其实很简单,如果用组件。不到5分钟就能完成一个基本功能的聊天室了,但如果有各类需求,就需要自行开发了。1 聊天记录问题:一般分为3类 (1).不记录聊天内容比较简单,通过Client发送内容来后,直接用...
  • 简单的socket聊天工具,实现在发送文件和语音聊天等功能,还能聊天的同时听音乐,分服务器端和客户端两部分
  • Android QQ、微信聊天消息界面设计原理实现 原理:Android平台上,典型的以腾讯的QQ、微信这些聊天消息界面通常可以采用ListView设计与实现,需要使用ListView 适配器Adapter的getItemViewType()和...
  • 请教各路大神,QQ聊天的气泡是怎么实现的呢.我的方法是 在Grid里面嵌套一个Border,定义了一个GeometryDrawing,问题是当文本内容多的时候,这个气泡会撑大不美观.请教更加合理的实现方式. <Grid Grid.Row="1" ...
  • 最近才仔细研究对话框的小三角如何实现,先来了解一下相关的知识: 先看代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type...
  • 花了一点时间对一个看似简单的...原理是:把表情代码提出出来,替换成几个空格,然后把表情swf放到textfield上面。你参考下,在目前来说,我看到别人的基本上也都差不多,标准完整让人满意没bug的没见过。  

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,757
精华内容 702
关键字:

聊天实现原理