在本文中,我们将带你了解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)
- asp.net-mvc – 在同一个流连接上返回多个结果以实现HTML5 Server Sent Events
- Browser/Server与Client/Server模式优缺点对比
- H5 Server-Sent 事件 - 单向消息传递
- HTML5 - Server-Sent Events
HTML Server-Sent 事件(html event.target)
Server-Sent 事件允许网页从服务器获得更新。Server-Sent 事件 - One Way Messaging
Server-Sent 事件指的是网页自动从服务器获得更新。 ( 推荐学习:html教程 )
以前也可能做到这一点,前提是网页不得不询问是否有可用的更新。通过 Server-Sent 事件,更新能够自动到达。
例如:Facebook/Twitter 更新、股价更新、新的博文、赛事结果,等等。
浏览器支持
表格中的数字指示完全支持 server-sent 事件的首个浏览器。
接收 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
我正在尝试的轻量级方法是:
客户端:
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的目的,因为客户端再次开始重新连接,因为正常轮询和消息传递被延迟.
现在,问题是:
在发送第一条消息并在同一连接上发送更多消息后,是否存在保持连接打开的本机方式?
解决方法
作为旁注,AsyncController的接口实际上不允许实现SSE流的干净方式;鉴于我使用的是Asp.NET MVC 4,我个人会实现HttpTaskAsyncHandler.
Browser/Server与Client/Server模式优缺点对比
browser/server具有分布性特点,可以随时随地进行业务处理。业务扩展简单方便,通过增加网页即可增加服务器功能。维护简单方便,只需要改变网页,即可实现所有用户的同步更新。开发简单,共享性强。 个性化特点明显降低,无法实现具有个性化的设计要求。操作
browser/server具有分布性特点,可以随时随地进行业务处理。业务扩展简单方便,通过增加网页即可增加功能。维护简单方便,只需要改变网页,即可实现所有用户的同步更新。开发简单,共享性强。
个性化特点明显降低,无法实现具有个性化的设计要求。操作的习惯性是以鼠标为最基本的操作方式,无法满足快速操作的要求。页面动态刷新,响应速度明显降低。专用性打印输出难以实现,尤其对票据等打印,难以实现套打输出。无法实现分页显示,给访问造成较大的压力。功能弱化,难以实现传统模式下的特殊功能要求。
client/server由于客户端实现与服务器的直接相连,没有中间环节,因此响应速度快。客户操作界面设计个性化,具有直观、简单、方便的特点,可以满足客户个性化的操作要求。同时由于开发是针对性的,因此,操作界面漂亮、形式多样,可以充分满足客户自身的个性化要求。
由于是针对性开发,因此缺少通用性的特点,业务变更或改变不够灵活,需要重新设计和开发,增加了维护和管理的难度,进一步的业务拓展困难较多。需要专门的客户端安装程序,分布功能弱,不能够实现快速部署安装和配置。兼容性差,对于不同的开发工具,相互之间很难兼容,具有较大的局限性。若采用不同工具,需要重新改写程序。 开发成本较高,需要具有一定专业水准的技术员才能完成。
H5 Server-Sent 事件 - 单向消息传递
虽然以前知道这个技术,但是一直没去了解过,今天在这里记录一下,先看W3school说的
这意味着可以做一些简单的消息推送
下面是我的代码:
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
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的相关知识,请在本站寻找。
本文标签: