GVKun编程网logo

HTML Server-Sent 事件(html event.target)

10

在本文中,我们将带你了解HTMLServer-Sent事件在这篇文章中,我们将为您详细介绍HTMLServer-Sent事件的方方面面,并解答htmlevent.target常见的疑惑,同时我们还将给

在本文中,我们将带你了解HTML Server-Sent 事件在这篇文章中,我们将为您详细介绍HTML Server-Sent 事件的方方面面,并解答html event.target常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的asp.net-mvc – 在同一个流连接上返回多个结果以实现HTML5 Server Sent Events、Browser/Server与Client/Server模式优缺点对比、H5 Server-Sent 事件 - 单向消息传递、HTML5 - Server-Sent Events

本文目录一览:

HTML Server-Sent 事件(html event.target)

HTML Server-Sent 事件(html event.target)

Server-Sent 事件允许网页从服务器获得更新。

Server-Sent 事件 - One Way Messaging

Server-Sent 事件指的是网页自动从服务器获得更新。 ( 推荐学习:html教程 )

以前也可能做到这一点,前提是网页不得不询问是否有可用的更新。通过 Server-Sent 事件,更新能够自动到达。

例如:Facebook/Twitter 更新、股价更新、新的博文、赛事结果,等等。

浏览器支持

表格中的数字指示完全支持 server-sent 事件的首个浏览器。

python-p-141.png

接收 Server-Sent 事件通知

EventSource 对象用于接收服务器发送事件通知:

实例

var source = new EventSource(demo_sse.PHP);
source.onmessage = function(event) {
    document.getElementById(result).innerHTML += event.data + <br>;
};

例子解释:

创建一个新的 EventSource 对象,然后规定发送更新的页面的 URL(本例中是 demo_sse.PHP)

每当接收到一次更新,就会发生 onmessage 事件

当 onmessage 事件发生时,把已接收的数据推入 id 为 result 的元素中

检测 Server-Sent 事件支持

在 TIY 实例中,我们编写了一段额外的代码来检测服务器发送事件的浏览器支持:

if(typeof(EventSource) !== undefined) {
    // 是的!支持服务器发送事件!
    // 一些代码.....
} else {
    // 抱歉!不支持服务器发送事件!
}

asp.net-mvc – 在同一个流连接上返回多个结果以实现HTML5 Server Sent Events

asp.net-mvc – 在同一个流连接上返回多个结果以实现HTML5 Server Sent Events

我试图在我的MVC 4 Web上设置一个轻量级的 HTML5 Server-Sent Event实现,而不使用其中一个库来实现套接字和类似物.
我正在尝试的轻量级方法是:

客户端:
EventSource(或IE的jquery.eventsource)

服务器端:
使用AsynchController进行长轮询(很抱歉在这里删除原始测试代码,但只是为了提出一个想法)

public class HTML5testAsyncController : AsyncController
    {
        private static int curIdx = 0;
        private static BlockingCollection<string> _data = new BlockingCollection<string>();
        static HTML5testAsyncController()
        {
            addItems(10);
        }
 //adds some test messages
        static void addItems(int howMany)
        {
            _data.Add("started");
            for (int i = 0; i < howMany; i++)
            {
                _data.Add("HTML5 item" + (curIdx++).ToString());
            } _data.Add("ended");
        }

// here comes the async action,'Simple'
        public void SimpleAsync()
        {
            AsyncManager.OutstandingOperations.Increment();

            Task.Factory.StartNew(() =>
            {
                var result = string.Empty; var sb = new StringBuilder();
                string serializedobject = null;
            //wait up to 40 secs that a message arrives
                if (_data.TryTake(out result,TimeSpan.FromMilliseconds(40000)))
                {
                    JavaScriptSerializer ser = new JavaScriptSerializer();
                    serializedobject = ser.Serialize(new { item = result,message = "MSG content" });
                    sb.AppendFormat("data: {0}\n\n",serializedobject);
                }
                AsyncManager.Parameters["serializedobject"] = serializedobject;
                AsyncManager.OutstandingOperations.Decrement();
            });
        }
  // callback which returns the results on the stream
        public ActionResult SimpleCompleted(string serializedobject)
        { ServerSentEventResult sar = new ServerSentEventResult(); 
            sar.Content = () => { return serializedobject; };
            return sar;

        }
  //pushes the data on the stream in a format conforming HTML5 SSE
        public class ServerSentEventResult : ActionResult
        {
            public ServerSentEventResult() { }
            public delegate string GetContent(); 
            public GetContent Content { get; set; }        
            public int Version { get; set; }
            public override void ExecuteResult(ControllerContext context)
            {
                if (context == null)
                {
                    throw new ArgumentNullException("context");
                } if (this.Content != null)
                {
                    HttpResponseBase response = context.HttpContext.Response;
                    // this is the content type required by chrome 6 for server sent events              
                    response.ContentType = "text/event-stream";

                    response.BufferOutput = false;                // this is important because chrome fails with a "Failed to load resource" error if the server attempts to put the char set after the content type          
                    response.Charset = null;
                    string[] newStrings = context.HttpContext.Request.Headers.GetValues("Last-event-id");
                    if (newStrings == null || newStrings[0] != this.Version.ToString())
                    {
                        string value = this.Content();
                        response.Write(string.Format("data:{0}\n\n",value));
                        //response.Write(string.Format("id:{0}\n",this.Version));
                    }
                    else
                    {
                        response.Write("");
                    }
                }
            }
        }
    }

问题出在服务器端,因为预期结果与实际发生的结果之间仍然存在很大差距.

预期结果:

> EventSource打开与服务器的流连接,
>服务器保持打开一段安全时间(比方说,2分钟),以防止线程从死客户泄漏,
>当服务器收到新的消息事件(并排入线程安全集合,如BlockingCollection)时,它们将在开放流中推送到客户端:

>消息1在T 0ms接收,在T x被推送到客户端
>消息2在T 200ms接收,在T x 200ms推送到客户端

实际行为:

> EventSource打开与服务器的流连接,
>服务器保持打开状态,直到消息事件到达(感谢长轮询)
>一旦收到消息,MVC就会推送消息并关闭连接.
> EventSource必须重新打开连接,这会在几秒钟后发生.

>消息1在T 0ms接收,在T x 3200ms推送到客户端

这是不行的,因为它失败了使用SSE的目的,因为客户端再次开始重新连接,因为正常轮询和消息传递被延迟.

现在,问题是:
在发送第一条消息并在同一连接上发送更多消息后,是否存在保持连接打开的本机方式?

解决方法

您希望使用 Response.Flush发送数据,而不是依赖于SimpleComplete来发送数据.通过执行AsyncManager.OutstandingOperations.Decrement(),您告诉AsyncController您已完成处理请求并且您已准备好发送响应并关闭连接.相反,您应该避免调用OutStandingOperations.Decrement()直到连接丢失等.每当您想要将消息推送到客户端时,您直接从某个后台线程调用 Response.Write和Response.Flush.此外,AsyncControllers具有默认超时,之后它们会自动关闭连接.为了解决这个问题,您需要使用 NoAsyncTimeoutAttribute进行相关操作.

作为旁注,AsyncController的接口实际上不允许实现SSE流的干净方式;鉴于我使用的是Asp.NET MVC 4,我个人会实现HttpTaskAsyncHandler.

Browser/Server与Client/Server模式优缺点对比

Browser/Server与Client/Server模式优缺点对比

browser/server具有分布性特点,可以随时随地进行业务处理。业务扩展简单方便,通过增加网页即可增加服务器功能。维护简单方便,只需要改变网页,即可实现所有用户的同步更新。开发简单,共享性强。 个性化特点明显降低,无法实现具有个性化的设计要求。操作

    browser/server具有分布性特点,可以随时随地进行业务处理。业务扩展简单方便,通过增加网页即可增加功能。维护简单方便,只需要改变网页,即可实现所有用户的同步更新。开发简单,共享性强。

    个性化特点明显降低,无法实现具有个性化的设计要求。操作的习惯性是以鼠标为最基本的操作方式,无法满足快速操作的要求。页面动态刷新,响应速度明显降低。专用性打印输出难以实现,尤其对票据等打印,难以实现套打输出。无法实现分页显示,给访问造成较大的压力。功能弱化,难以实现传统模式下的特殊功能要求。

    client/server由于客户端实现与服务器的直接相连,没有中间环节,因此响应速度快。客户操作界面设计个性化,具有直观、简单、方便的特点,可以满足客户个性化的操作要求。同时由于开发是针对性的,因此,操作界面漂亮、形式多样,可以充分满足客户自身的个性化要求。

    由于是针对性开发,因此缺少通用性的特点,业务变更或改变不够灵活,需要重新设计和开发,增加了维护和管理的难度,进一步的业务拓展困难较多。需要专门的客户端安装程序,分布功能弱,不能够实现快速部署安装和配置。兼容性差,对于不同的开发工具,相互之间很难兼容,具有较大的局限性。若采用不同工具,需要重新改写程序。 开发成本较高,需要具有一定专业水准的技术员才能完成。

H5 Server-Sent 事件 - 单向消息传递

H5 Server-Sent 事件 - 单向消息传递

虽然以前知道这个技术,但是一直没去了解过,今天在这里记录一下,先看W3school说的

clipboard.png
这意味着可以做一些简单的消息推送
下面是我的代码:
html页面

<div>
    <input type="hidden">
    <div id="test">倒计时</div>
    <button id="open" type = "button">开启签到</button>
    <button id="close" type = "button">结束签到</button>
</div>
<div>
    <table>
        <tr></tr>
    </table>
</div>

js代码:

var source,message,timer;
/**
 * 开启签到 - 开始检查服务端是否有更新
 */
$("#open").click(function () {
    countdown();
    if(typeof(EventSource)!=="undefined") {
        source = new EventSource("http://10.3.140.139:8082/index/test/getuser");
        source.onmessage=function(event)//接收到消息
        {
            message = event.data;
            var len = message.length;
            if (len > 0) {
                message = JSON.parse(message);
                $(".handle_message tr").append(code(message[''head_pic''],message[''username'']));
            }
        };
    } else {
        layer.msg(''抱歉,你的浏览器不支持 server-sent 事件...'');
    }
});

/**
 * 关闭监听
 */
$("#close").click(function () {
    cz_close();
});
/**
 * 关闭监听操作
 */
function cz_close() {
    timer = $(".paging").val();
    clearTimeout(timer);
    $(''#test'').html(''签到结束'');
    source.close();
    $.post("http://10.3.140.139:8082/index/test/clearcache");
    layer.msg(''停止监听服务器更新'');
}

/**
 * 追加代码
 * @returns {string}
 */
function code(pic,name) {
    var code = ''<td>'' +
        ''<img src="''+ pic +''" alt="http://tva2.sinaimg.cn/large/005ucgoIly1g3iiq7a591j30jg0jgwl0.jpg">'' +
        ''<p><span>''+ name +''</span></p>'' +
        ''</td>'';
    return code;
}

/**
 * 倒计时
 */
function countdown() {
    layui.use(''util'', function(){
        var util = layui.util,
        serverTime = new Date().getTime(),
        endTime = serverTime + (2 * (60 * 1000));
        util.countdown(endTime, serverTime, function(date, serverTime, timer){
            $(".paging").val(timer);
            var str = date[2] + ''分'' + date[3] + ''秒'';
            if (date[0] == 0 && date[1] == 0 && date[2] == 0 && date[3] == 0) {
                clearTimeout(timer);//清除定时器
                cz_close();
            }else {
                $(''#test'').html(''剩余时间:''+ str);
            }
        });
    });
}

php代码:

/**
     * @return mixed
     * 学生端签到页面
     */
    public function index()
    {
        return $this->fetch();
    }

    /**
     * @return mixed
     * 教师端开启签到页面
     */
    public function demo()
    {
        return $this->fetch();
    }

    /**
     * 将签到的学生加入缓存
     */
    public function post()
    {
        if ($_POST) {
            $img = self::curlInfo();
            $_POST[''head_pic''] = $img;
            $info = json_encode($_POST);
            Cache::set(''user_info'',$info);
        }
    }

    /**
     * 缓存取出用户
     */
    public function getUser ()
    {
        //取出并清除当前缓存
        $info = Cache::pull(''user_info'');
        ////服务端事件标准规定(将MIME类型设为text/event-stream)
        header(''Content-Type: text/event-stream'');
        ////告诉Web服务器关闭Web缓存
        header(''Cache-Control: no-cache'');
        echo "data:{$info}\n\n";
        //立即发送数据(而不是先缓冲起来,等到PHP代码执行完毕再发送)
        flush();
    }

    /**
     * 清除缓存
     */
    public function clearCache ()
    {
        Cache::clear();
    }

    /**
     * @return mixed
     * 获取用户随机头像
     */
    protected function curlInfo ()
    {
        $url = ''https://api.66mz8.com/api/rand.pic.php?type=%E4%B8%AA%E6%80%A7&return=json'';
        $curl = curl_init();//初始化CURL句柄
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($curl,CURLOPT_HTTPGET,true);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        $info = json_decode($output,true);
        $img = $info[''imgurl''];
        return $img;
    }

参考链接:http://www.w3school.com.cn/ht...
http://www.hangge.com/blog/ca...

HTML5 - Server-Sent Events

HTML5 - Server-Sent Events

1. 服务端编码

@GetMapping(path = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter sse() throws Exception {
        final SseEmitter emitter = new SseEmitter();
        final AtomicInteger i = new AtomicInteger(0);
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1 * 1000);
                        emitter.send(i.addAndGet(1));
                    } catch (InterruptedException e) {
                        throw new UnsupportedOperationException("Not yet implemented!");
                    } catch (IOException e) {
                        throw new UnsupportedOperationException("Not yet implemented!");
                    }
                }
            }
        }).start();
        return emitter;
    }

2. 客户端编码

$(function () {
            var source = new EventSource("/sse");
            source.onmessage = function (event) {
                $(''#result'').html(event.data);
            };
        });

EventSource为客户端脚本的JavaScript对象

关于HTML Server-Sent 事件html event.target的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于asp.net-mvc – 在同一个流连接上返回多个结果以实现HTML5 Server Sent Events、Browser/Server与Client/Server模式优缺点对比、H5 Server-Sent 事件 - 单向消息传递、HTML5 - Server-Sent Events的相关知识,请在本站寻找。

本文标签: