使用HTML5的Server-sent技术,Go服务器向页面推送消息
2017-06-05 15:44
661 查看
随学随记,留备查
修正时间:201707121017
修正原因:进一步学习server-sent后,发现先前描述的不当之处,现改之。
1、本来今天学习worker,想实验服务器与页面推送数据,却偶然的发现了HTML5的新web api:EventSource
2、看了下w3school样例,简单好用。于是乎试试看
3、HTML代码 serversend.html:
4、Go代码 main.go:
5、运行Go程序,打开浏览器。页面上只显示“服务器当前时间:”,等了1分钟也没显示时间……
6、搜索无果,用chrome的开发者工具也没与w3school样例对比出个所以然,于是想到用Fiddler看看到底哪里不对了。
7、费了半天劲在Fiddler中也没发现两者返回的不一致之处,后来突然在HexView中看到,w3school返回的数据末尾有两个"..",16进制是0A0A;我的没有。难道是这个问题?
8、试试看,在Go程序中把返回字符串结尾加上,“\n\n”,在运行试试看。哎我去,出来时间了。当时真是一万个xxx奔跑而过……原来w3school里面的php代码示例中的“\n\n”不是为了好看的,是关键所在!
9、痛定思痛,还是应该好好查看下W3C官方的技术文档才是正道。偷下懒却浪费的更多时间!
10、测试发现,chrome刷新间隔3秒钟,firefox刷新间隔5秒钟。这有点太慢了。要是能改刷新时间就好了。
11、这回学乖了,查阅MDN文档,发现有如下格式:
event:事件类型.
data:消息的数据字段.
id:事件ID.
retry:一个整数值,指定了重新连接的时间(单位为毫秒),如果该字段值不是整数,则会被忽略.
12、这里的retry不就是我所需要的吗?马上加上试试,运行之!OK,正如所需!
13、至此,server-sent发送事件练习告一段落,也踩了一个不大不小的坑!学友们一定要记住在消息末尾加上“\n\n”,切记!
14、main.go 最终版:
修正如下:
1、当时只是简单的测试server-sent,没细看。今天发现先前理解的偏差。
2、“retry”实际上是,服务器通知浏览器多长时间重新创建连接。而不是数据刷新的时间。
3、但是,不设置"retry",数据并不会实时刷新!为什么?原来,当前go函数getDate接收到请求,推送一次时间数据后,函数就执行完毕退出了,那么连接也就被断开了;所以浏览器只能是过了超时时间,再重新连接,依次重复。
4、那就需要改造下getDate函数,让他一直发数据不退出。那就加个for循环圈住。但是,实际效果却是,浏览器接收不到数据或者依次接收一大堆数据。原因是,http.ResponseWriter默认带发送数据缓冲区的,所以for循环内会不断的填充发送缓冲区,而不会立即发送给浏览器。
5、这时,就想http.ResponseWriter应该有类似flush的方法就好了。但是看代码有点不好找,go语言这一点确实没有声明接口继承来的方便。在server.go看到type response struct {},应该就是getDate函数的w参数的实参了。其实现了Flush()方法。而Flush()方法对应的接口是Flusher。那就加上类型断言,来将w转成Flusher接口。
6、最终代码如下;
7、运行起来,浏览器就会每隔500毫秒接收到依次数据推送,很好很方便!
修正时间:201707121017
修正原因:进一步学习server-sent后,发现先前描述的不当之处,现改之。
1、本来今天学习worker,想实验服务器与页面推送数据,却偶然的发现了HTML5的新web api:EventSource
2、看了下w3school样例,简单好用。于是乎试试看
3、HTML代码 serversend.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>EventSource测试</title> </head> <body> <h1>服务器当前时间:</h1> <div id="result"></div> <script> if (typeof(EventSource) !== "undefined") { var source = new EventSource("getdate"); source.onmessage = function(event) { document.getElementById("result").innerHTML += event.data + "<br>"; }; } else { document.getElementById("result").innerHTML = "抱歉,你的浏览器不支持 server-sent 事件..."; } </script> </body> </html>
4、Go代码 main.go:
package main import ( "fmt" "html/template" "net/http" "time" ) func viewDate(w http.ResponseWriter, r *http.Request) { t, _ := template.ParseFiles("serversend.html") _ = t.Execute(w, nil) } func getDate(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/event-stream;charset=utf-8") w.Header().Set("Cache-Control", "no-cache") dtstr := "data: " + fmt.Sprint(time.Now()) w.Write([]byte(dtstr)) } func main() { http.HandleFunc("/", viewDate) http.HandleFunc("/getdate", getDate) http.ListenAndServe("", nil) }
5、运行Go程序,打开浏览器。页面上只显示“服务器当前时间:”,等了1分钟也没显示时间……
6、搜索无果,用chrome的开发者工具也没与w3school样例对比出个所以然,于是想到用Fiddler看看到底哪里不对了。
7、费了半天劲在Fiddler中也没发现两者返回的不一致之处,后来突然在HexView中看到,w3school返回的数据末尾有两个"..",16进制是0A0A;我的没有。难道是这个问题?
8、试试看,在Go程序中把返回字符串结尾加上,“\n\n”,在运行试试看。哎我去,出来时间了。当时真是一万个xxx奔跑而过……原来w3school里面的php代码示例中的“\n\n”不是为了好看的,是关键所在!
9、痛定思痛,还是应该好好查看下W3C官方的技术文档才是正道。偷下懒却浪费的更多时间!
10、测试发现,chrome刷新间隔3秒钟,firefox刷新间隔5秒钟。这有点太慢了。要是能改刷新时间就好了。
11、这回学乖了,查阅MDN文档,发现有如下格式:
event:事件类型.
data:消息的数据字段.
id:事件ID.
retry:一个整数值,指定了重新连接的时间(单位为毫秒),如果该字段值不是整数,则会被忽略.
12、这里的retry不就是我所需要的吗?马上加上试试,运行之!OK,正如所需!
13、至此,server-sent发送事件练习告一段落,也踩了一个不大不小的坑!学友们一定要记住在消息末尾加上“\n\n”,切记!
14、main.go 最终版:
package main import ( "fmt" "html/template" "net/http" "time" ) func viewDate(w http.ResponseWriter, r *http.Request) { t, _ := template.ParseFiles("serversend.html") _ = t.Execute(w, nil) } func getDate(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/event-stream;charset=utf-8") w.Header().Set("Cache-Control", "no-cache") dtstr := "data: " + fmt.Sprint(time.Now()) + "\n\n" dtstr = dtstr + "retry:" + "1000" + "\n\n" w.Write([]byte(dtstr)) } //主程序 func main() { http.HandleFunc("/", viewDate) http.HandleFunc("/getdate", getDate) http.ListenAndServe("", nil) }
修正如下:
1、当时只是简单的测试server-sent,没细看。今天发现先前理解的偏差。
2、“retry”实际上是,服务器通知浏览器多长时间重新创建连接。而不是数据刷新的时间。
3、但是,不设置"retry",数据并不会实时刷新!为什么?原来,当前go函数getDate接收到请求,推送一次时间数据后,函数就执行完毕退出了,那么连接也就被断开了;所以浏览器只能是过了超时时间,再重新连接,依次重复。
4、那就需要改造下getDate函数,让他一直发数据不退出。那就加个for循环圈住。但是,实际效果却是,浏览器接收不到数据或者依次接收一大堆数据。原因是,http.ResponseWriter默认带发送数据缓冲区的,所以for循环内会不断的填充发送缓冲区,而不会立即发送给浏览器。
5、这时,就想http.ResponseWriter应该有类似flush的方法就好了。但是看代码有点不好找,go语言这一点确实没有声明接口继承来的方便。在server.go看到type response struct {},应该就是getDate函数的w参数的实参了。其实现了Flush()方法。而Flush()方法对应的接口是Flusher。那就加上类型断言,来将w转成Flusher接口。
6、最终代码如下;
func getDate(w http.ResponseWriter, r *http.Request) { for { w.Header().Set("Content-Type", "text/event-stream;charset=utf-8") w.Header().Set("Cache-Control", "no-cache") dtstr := "data: " + fmt.Sprint(time.Now()) + "\n\n" w.Write([]byte(dtstr)) if f, ok := w.(http.Flusher); ok { f.Flush() } else { fmt.Println("no flush") } time.Sleep(500 * time.Millisecond) } }
7、运行起来,浏览器就会每隔500毫秒接收到依次数据推送,很好很方便!
相关文章推荐
- HTML5中的服务器‘推送’技术 -Server-Sent Events
- SSE(Server-sent events)技术在web端消息推送和实时聊天中的使用
- [HTML] HTML5中的服务器‘推送’技术(1) -Server-Sent Events
- HTML5支持服务器发送事件(Server-Sent Events)-单向消息传递数据推送(C#示例)
- HTML5服务器推送消息之Server-Sent Events
- go服务器向页面推送消息
- HTML5中的服务器‘推送’技术 -Server-Sent Events
- html5:服务器事件推送(server-sent events)Asp.net
- 使用tomcat8.0.36实现的websocket技术,实现向单个以及全部用户实时推送消息的功能
- asp.net服务器推送(ServerPush)和客户端拉拽技术
- 服务器推送技术原理分析及dwr框架简单的使用
- HTML5 服务器推送事件(Server-sent Events)实战开发
- Web端服务器推送技术原理分析及dwr框架简单的使用
- PHP Web实时消息后台服务器推送技术-GoEasy
- PHP Web实时消息后台服务器推送技术---GoEasy
- node.js Web实时消息后台服务器推送技术---GoEasy
- 使用EventSource实现页面消息推送 与 websocket 的区别
- Ruby Web实时消息后台服务器推送技术-GoEasy
- Web端服务器推送技术原理分析及dwr框架简单的使用
- Python web实时消息服务器后台推送技术方案---GoEasy