前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实现服务器推送消息到客户端ServerPush

实现服务器推送消息到客户端ServerPush

作者头像
静心物语313
发布2020-03-24 10:52:31
3K0
发布2020-03-24 10:52:31
举报

1.实验目的:

1.演示ServerPush服务器推送消息给浏览器端的功能
2.要明白,对http协议来讲,是不可能服务器给给浏览器主动发送信息的,因为不能满足,“请求---》响应”的机制
3.这里主要是使用的一个“长链接”的机制,模拟--》》》“服务器推送消息”(。。。我的理解:就是让浏览器不断的向服务器发送请求。。。服务器收到请求后,响应,就是长链接)

2.实验步骤:

1.新建一个ServerPushChat.ashx一般处理程序。
    1.修改ContentType为application/json。
    2.获取请求的对象。Request。设置变量名 为me。
    3.设置一个死循环,死循环中,内容:
        1.根据从请求报文中获取的我是谁---》me,根据me这个变量名字到数据库中查询是否有这个变量名字的消息。
        2.没有就继续下一轮的循环。
        3.否则,数据库中的行数不是零了。就读出每个列的数据,序列化为json发送到浏览器端。同时删除这条数据(因为对方已经收到了。这个消息,所以就删除这条消息了),同时结束循环。break或者return;
    4.在浏览器重输入ServerPushChat.ashx,打开开发者工具,可以看见ServerPushChat.ashx的状态时是pending,-->说明是在等待着服务器的响应信息。(暴露问题:while死循环一直在,所以CPU占用太高。解决方案:在下一轮循环之前,加上一个Thread.Sleep(500)毫秒;


2.新建一个ServerPushChat.html页面
    1.这里没有考虑安全性问题。(用户验证)
    2.设置点击“登录”后,向服务器端ServerPushChat.ashx索要信息。
    3.设置点击“发送”后,向服务器端ServerPushChat.ashx请求报文,内容如下:
        1.我是谁;
        2.消息发给谁;
        3.消息内容;
        4.ServerPushChat.ashx接受到这三个变量,进行插入(这里没有做用户名,消息非空验证,)插入成功后,向浏览器端发送,json序列的“ok”;
    4.接着对“发送”按钮的点击事件,写ajax
    5.从ServerPushChat.ashx获取是成功的发送了--》ok,还是没有发送成功。---》显示消息不识别
    6.清除发送框中的内容。
    7.接着对“登录”按钮的点击事件,写ajax
        1.由于请求的都是ServerPushChat.ashx这个一般处理程序。所以要使用action进行识别,到底是“登录”点击事件,还是“发送”点击事件。
        2.成功从服务器端接收到了,将收到的消息,显示在ul的列表中。
        3.接受成功后,接着继续,请求ServerPushChat.ashx
            1.这里需要封转一个function,封装的内容,是接收成功后和接受失败后都继续该function。(类似递归,自己调用自己)
        4.设置“登录”按钮为不可用状态,免得用户重复点击
            1.$(this).attr("disabled","disabled");

3.代码:

ServarPustChat.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>聊天室</title>
    <script src="jquery.min.js"></script>
    <script type="text/javascript">
        //抽出来的一个function,用于接受消息
        var recv = function () {
            var me = $("#me").val();
            $.ajax({               //登录成功后只是接收了一次,所以这里将抽出一个单独的function
                type: "post", url: "ServarPustChat.ashx",
                data: { action: "receive", me: $("#me").val() },
                success: function (data) {
                    $("#ulMsg").append($("<li>" + data.FromUserName + "对我说:" + data.Msg + "</li>"));
                    recv();//接收成功后仍然请求
                },
                error: function () {
                    recv();//接收失败后任然请求(原因是网路的暂时故障)

                }
            });
        };


        $(function () {
            //1.发送消息,此处发现都是请求的ServarPustChat.ashx,使用action进行区分
            $("#btnSend").click(function () {
                $.ajax({
                    type: "post", url: "ServarPustChat.ashx",
                    //2.发送点击事件  我是,给谁,内容
                    data: { action: "send", Msg: $("#msg").val(), me: $("#me").val(), tousername: $("#toUserName").val() },
                    success: function (data) {
                        if (data.Status == "ok") {
                            $("#ulMsg").append($("<li>我对:" + $("#toUserName").val() + "说:" + $("#msg").val() + "</li>"));
                            //清空文本框
                            $("#msg").val("");
                        } else {
                            alert("发送错误,返回的报文不能识别");
                        }

                    },
                    error: function () {
                        alert("发送错误");
                    }

                });

            });
            $("#btnLogin").click(function () {
                recv();//点击上线后,就不断的发送请求,达到获得信息的目的
                //设置“上线”按钮为不可用状态,免得用户重复点击
                $("#btnLogin").attr("disabled","disabled");

            });


            /*
            //登录接收消息
            $("#btnLogin").click(function () {
                var me = $("#me").val();
                $.ajax({               //登录成功后只是接收了一次,所以这里将抽出一个单独的function
                    type: "post", url: "ServarPustChat.ashx",
                    data: { action: "receive", me: $("#me").val() },
                    success: function (data) {
                        $("#ulMsg").append($("<li>" + data.FromUserName+"对我说:"+data.Msg+"</li>"));

                    },
                    error: function () {
                        alert("接受消息失败");

                    }


                });


            });
            */

        });

    </script>


</head>
<body>
    我是:<input id="me" type="text"/><input type="button" id="btnLogin" value="上线" /><br />
    <br />
    发送给:<input id="toUserName" type="text" />发送内容:<input id="msg" type="text" /><input type="button" id="btnSend" value="发送"/>
    <br />
        <ul id="ulMsg">

    </ul>
</body>
</html>

ServarPustChat.ashx

<%@ WebHandler Language="C#" Class="ServarPustChat" %>

using System;
using System.Web;
using System.Data;
using Web1;
using System.Data.SqlClient;
using System.Web.Script.Serialization;

public class ServarPustChat : IHttpHandler {

    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "application/json";//1.修改
        //当向ServarPustChat.ashx文件进行请求信息的时候,加上请求的对象
        //me=rupeng
        //ServarPustChat.ashx?me=rupeng

        //2.获取请求报文中的请求对象
        string me = context.Request["me"];

        //最后添加的部分。。。。。
        string action=context.Request["action"];
        if ("send"==action)
        {

            string tousername = context.Request["tousername"];
            string msg = context.Request["Msg"];
            SqlHelper.ExecuteNonQuery("insert into t_msgs(FromUserName,ToUserName,Msg) values(@FromUserName,@ToUserName,@Msg)"
                , new SqlParameter("@ToUserName", tousername),
                new SqlParameter("@FromUserName", me),
                new SqlParameter("@Msg", msg));
            context.Response.Write(new JavaScriptSerializer().Serialize(new { Status = "ok" }));


        }
        else if ("receive" == action)
        {
            //3.根据me这个变量名字到数据库中查询是否有这个变量名字的消息。
            //4.此处设置一个死循环,让请求不断地查询
            while (true)
            {
                DataTable dt = SqlHelper.ExecuteQuery("select top 1 * from T_Msgs where ToUserName=@ToUserName", new SqlParameter("@ToUserName", me));
                if (dt.Rows.Count <= 0)
                {
                    //System.Threading.Thread.Sleep(500);//避免一直在查询的问题,缓解cpu的压力
                    continue;//如果查询的时空的继续查询
                }
                else
                {
                    DataRow row = dt.Rows[0];//取出第一行
                    long id = (long)row["id"];
                    string fromUserName = (string)row["FromUserName"];
                    string msg = (string)row["Msg"];
                    //发送完的信息删除操作
                    SqlHelper.ExecuteNonQuery("delete from T_Msgs where Id=@id", new SqlParameter("@id", id));
                    //将收到的消息发送给me
                    var data = new { FromUserName = fromUserName, Msg = msg };
                    string json = new JavaScriptSerializer().Serialize(data);
                    context.Response.Write(json);//(返回浏览器端)
                    break; //返回后结束循环
                }
            }

        }
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

3.运行效果图

这里写图片描述
这里写图片描述

4.总结:

ServrPush对服务器的压力还是很大的,服务器并行处理的数量有限,大型的网站有很多的优化策略,但是对客户端可以使用WebScoket(HTML5技术),在浏览器中写Socket,低版本的html中,只能用XmlHttpRequest(XHR)但是效率低,微软推出了一个框架,SignalR(当前浏览器支持html5就用WebScoket,不支持就用XHR)。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.实验目的:
  • 2.实验步骤:
  • 3.代码:
    • ServarPustChat.html
      • ServarPustChat.ashx
      • 3.运行效果图
      • 4.总结:
      相关产品与服务
      云开发 CLI 工具
      云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档