<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>EventSource</title>
</head>
<body>
<script>
window.onload=function(){
name();
function name(){
var username=prompt("请输入您的昵称");
if(!username){
return false;
}
var xml=new XMLHttpRequest();
xml.open("POST","/addUser");
xml.send("name="+username);
xml.onreadystatechange=function(){
if(xml.status=200&&xml.readyState==4){
var res=JSON.parse(xml.responseText)
if(res.success=="ok"){
alert("欢迎你的加入");
window.hiddenValue.value=res.name;
var es = new EventSource("/chat");
es.addEventListener("message", function(e){
var temp=document.createElement("li");
temp.innerHTML= e.data;
window.message.scrollIntoView();
window.content.appendChild(temp);
},false);
}else{
alert(res.msg+",如果你还想加入,行刷新重新输入用户名称");
//本来用的递归,但是体验不好,就改了
//name();
}
}
}
}
var div=document.getElementsByTagName("div")[0]
div.style.width=window.innerWidth+"px";
}
function sendMessage(){
var message=window.message.value;
if(message.trim()){
var b=new XMLHttpRequest();
b.open("POST","/chat");
b.send("message="+window.message.value+"&name="+ window.hiddenValue.value);
}
} </script>
<div>
<ul id="content">
</ul>
</div>
<input type="text" name="message" id="message" /><input type="button" value="发送" onclick="sendMessage()"/>
<input type="hidden" id="hiddenValue">
</body>
</html>
var server=require("http");
var url=require("url");
var file=require("fs");
var querystring=require("querystring");
var clientName=[];
var responseArray=[]; server.createServer(function (request, response) {
var message="";
var name="";
var urlContent=url.parse(request.url); //首页
if(urlContent.pathname=="/"){
response.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
file.readFile("../views/Index.html",function(err,data){
response.end(data);
})
return false;
}
else if(urlContent.pathname=="/chat"){ //发送消息
if(request.method=="POST"){ //并不能根据response得到正确的name索引,所以前台传递name
request.on("data",function(data){
data= querystring.parse(data.toString());
message+=decodeURIComponent(data.message.trim());
name+=decodeURIComponent(data.name.trim());
})
request.on("end",function(){
responseArray.forEach(function(i){
i.write("data:"+name+"说:"+message+"\n\n");
})
})
response.end();
}else{ //建立长连接,保存相应
responseArray.push(response);
response.writeHead(200,{"Content-Type":"text/event-stream"});
response.write("data:已连接至服务器\n\n");
request.connection.on("end",function(){
var index=responseArray.indexOf(response)
clientName.splice(index,1);
responseArray.splice(index,1);
response.end();
})
}
}else if(urlContent.pathname=="/addUser"){ //添加用户名
request.on("data",function(data){
data= querystring.parse(data.toString().trim());
name+=decodeURIComponent(data.name.trim());
});
request.on("end",function(){
response.writeHead(200,{"Content-Type":"text/json;charset=utf-8"});
if(clientName.some(function(i){
if(i==name) return true;
})){
response.write("{\"success\":\"fail\",\"msg\":\"用户名重复\"}")
}else{
response.write("{\"success\":\"ok\",\"name\":\""+name+"\"}");
responseArray.forEach(function(i){
i.write("data:欢迎"+name+"的加入"+"\n\n");
})
clientName.push(name);
}
response.end(); })
}
else{
response.writeHead(404,{"Content-Type":"text/json"});
response.end();
}
}).listen(8012);

后台使用Node.js  博主是一个新人,会有很多不太适合的代码,希望大家能多多帮助。代码中注意路径问题。代码仍有缺陷,现在连接断开,不一定能够删除用户名称。以下的总结都是基于上面的代码的,如果有其他情况,麻烦您给我说一下,谢谢。

 
可以跟服务器建立一个保持连接状态的连接,这样服务器能在服务端来对客户端推送信息。服务端在推送的时候要注意格式。write的内容必须是data:内容的,当write中的内容 有一个空行的时候就会推送消息,推送后,会触发EventSource的message事件,事件对象的data属性为推送的消息内容。
当write的时候发现客户端不再保持连接的时候,就会断开连接,如果还在write,就会触发write after end错误。只有服务端第一次wirte的时候才算连接成功,第一次write即使没有空格不进行推送,客户端也会得到200的状态,正式建立连接。如果服务端没有进行及时的write,则客户端认为还在请求过程中,等待服务端响应,会有一个等待时间,在等待的时间内write会正确的建立200链接。如果超过等待时间还是没有write,则请求将会失败,将重新发起请求。如果服务端明确发回404,并且response结束,则不会再次发出请求,否则,长连接请求会一直等待正式建立连接,并过时,再请求。
第一个长连接请求在进行请求的时候,一直没有建立正式的连接,超时后,会再次发送一个连接,在Chrome中观看的话,同一个network发了两次请求,但是这两次请求的是不同的请求
 
open事件为服务器连接打开的时候触发
error当发生错误的时候出发
 
如果服务器一直不触发messag事件,则过了一段时间后,不管还以前的连接是否还在,都会重新发起一个请求。服务器与客户端针对一个EventSource的request和response只存在一个,用前面的response.write的时候,将不会推送到客户端(此response已经被客户端放弃),如果连接建立后,服务器停掉了,则客户端会一直发送长连接请求。当在客户端使用eventsource的close或者关闭网页的时候,触发自己和服务器对应的request.connection的end事件。

EventSource的更多相关文章

  1. Html5实践之EventSource

    最近尝试了一下服务器端的推送,之前的做法都是客户端轮询,定时向服务器发送请求.但这造成了我的一些困扰: 1:轮询是由客户端发起的,那么在服务端就不能判别我要推送的内容是否已经过期,因为我很难判断某个信 ...

  2. EventSource (node.js 与 OC)

    node.js服务器代码: var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, ...

  3. HTML5 EventSource的用法

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. 服务端事件EventSource揭秘

    服务端推 服务端推,指的是由服务器主动的向客户端发送消息(响应).在应用层的HTTP协议实现中,"请求-响应"是一个round trip,它的起点来自客户端,因此在应用层之上无法实 ...

  5. H5 EventSource 实现web页面推送功能demo

    /** * H5 EventSource 实现web页面推送功能demo */ var serverData,statusDiv; var SERVER_URL = "index.php&q ...

  6. polyfill-eventsource added missing EventSource to window ie浏览器 解决方案

    今天遇到一个 ie浏览器显示空白,报错内容是: polyfill-eventsource added missing EventSource to window的问题, import 'babel-p ...

  7. EventSource 对象用于接收服务器发送事件通知,是网页自动获取来自服务器的更新

    //--------------------------------客户端代码----------------------------- if(typeof(EventSource) !== &quo ...

  8. 通过html5 的EventSource来进行数据推送

    以往我们要获取服务器的数据更新,一般通过ajax的定时请求,不过这样效率就低了.我们通过html5的EventSource可以很方便的获取服务器的数据更新,不过IE好像不支持.   例1如下: ind ...

  9. 【JavaScript】论一个低配版Web实时通信库是如何实现的之二( EventSource篇)

    前情提要 「 话说上回说到!那WebSocket大侠,巧借http之内力,破了敌阵的双工鸳鸯锁,终于突出重围. 然而玄难未了,此时web森林中飞出一只银头红缨枪,划破夜色. "莫非!?&qu ...

随机推荐

  1. 11. 星际争霸之php设计模式--备忘模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  2. 10. 星际争霸之php设计模式--原型模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  3. HTML5 UI框架Kendo UI Web自定义组件(一)

    Kendo UI Web包含数百个创建HTML5 web app的必备元素,包括UI组件.数据源.验证.一个MVVM框架.主题.模板等.在Kendo UI Web中如何创建自定义组件呢,在下面的文章中 ...

  4. s3c2440 移值u-boot-2016.03 第5篇 支持dm9000 识别

    1, 通过查看 /drivers/net/Makefile 发现想要编译上,需要添加宏 /include/configs/smdk2440.h 中添加 #define CONFIG_DRIVER_DM ...

  5. 锁表 for update

    select for update 是为了在查询时,避免其他用户以该表进行插入,修改或删除等操作,造成表的不一致性. 举几个例子:select * from t for update 会等待行锁释放之 ...

  6. html+css创建提示框

    看到下面的效果了吗? 本来我们站点是用下面的图片做的背景, 但是后期当更改完框中的提示内容,并且更新内容较多的时候,发现内容溢出了,如下图: 但是背景图片不能自动拉伸,还得重新做一张背景图,这样就导致 ...

  7. quick Cocos2dx lua 接anysdk

    quick3.3 的quick\samples\anysdk中有例子,具体用法可以参考官方文档,将的非常详细. 1.框架接口设计 系统介绍 必接入流程简要描述 消息通知 可扩展性 测试模式 添加测试账 ...

  8. easyui DataGrid 工具类之 Utils class

    import java.lang.reflect.InvocationTargetException;import java.text.ParseException;import java.text. ...

  9. Unity中通过类名字符串取组件类型的方法(Types.GetType用法)

    正常调用Type.GetType取不到组件,因为会先创建实例在获取,而Unity组件无法通过new来创建. 第二种创建方式是通过程序集,具体如下 Assembly.GetExecutingAssemb ...

  10. SnowNLP:一个处理中文文本的 Python 类库

    https://segmentfault.com/a/1190000000362372