从websocket看go的应用
Go是互联网时代的通用编程语言。这样它就和命令行时代的C语言、图示界面时代的C++、以及互联网早期的Java语言等有不同的侧重。它强调保持自身的精巧和独立,从而能配合现有的基础框架,也能比较容易地加入新的技术。 最近使用websocket完成了一个比较满意的设计。此处,我希望能通过一个很小的示例,展示如何使用Go,通过浏览器启动和监查远端窗口系统下的程序。重点不是系统的完备,而是要突出Go语言编程的简洁。 websocket是一种建立浏览器和服务器双向实时通信的技术,是对单向http请求响应方式的提升。我设计的系统要求能长时间显示更新一个程序的运行结果,这样直接使用http轮询的代价太高。幸运的是,我可以选择客户使用的浏览器,而Chome和Safari都己经支持websocket的了。 我们先直接看程序吧。
package main
import (
"code.google.com/p/go.net/websocket"
"io"
"net/http"
"os/exec"
"html/template"
)
func main() {
http.HandleFunc("/", homeHandler)
http.Handle("/ws", websocket.Handler(wsHandler))
http.ListenAndServe(":7224", nil)
}
func wsHandler(ws *websocket.Conn) {
for {
s := ""
if e := websocket.Message.Receive(ws, &s); e != nil {
break
}
c := exec.Command("cmd", "/C", s)
if s, e := c.StderrPipe(); e == nil {
go io.Copy(ws, s)
}
if s, e := c.StdoutPipe(); e == nil {
if e := c.Start(); e == nil {
io.Copy(ws, s)
}
}
}
ws.Close()
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
homeTpl.Execute(w, r.Host)
}
var homeTpl = template.Must(template.New("ws").Parse(`<html>
<textarea id=idout rows=24 cols=72></textarea><hr>
<input id=idin type=search placeholder='Enter a DOS command '
onchange='send(this.value)'></input>
<script>
var vout=document.getElementById('idout')
var vin = document.getElementById('idin')
var wscon = new WebSocket("ws://{{.}}/ws")
wscon.onclose = function(e) {vout.value = 'websocket closed'}
wscon.onmessage = function(e) { vout.value += e.data }
function send(s) {
vout.value = ""
wscon.send(s)
}
</script>
`))
import引进必要的函数包: websocket没有在Go标准包里,所以需要给出它所在的URL。io包我们使用了它的Copy函数完成字节的传输。http包提供了搭建网页服务器的一切资源。exec使我们可以运行操作系统提供的命令。而template此处用来处理HTML写的网页。 主函数main非常利索:注册homeHandler处理主页请求,而wsHandler处理websocket的请求,然后ListenAndServe启动服务器。 homeHandler更是简单,就是直接使用template包的Execute函数执行主机名Host的替换,使浏览器能指向正确的websocket的URL。 变量homeTpl使用template包把一个代表HTML主页的字符串Parse分析成模板,其中的{{.}}会被上述Execute时给出的r.Host替换。 而此HTML字串只是简单的描述了主页会显示一个textarea和一个input。后者用来输入待执行的操作系统命令,而前者用来显示命令执行的输出。script里是Javascript写的控制逻辑,它建立一个websocket连接,并且如果input内容改变,则使用websocket的send函数发送给服务器注册的wsHandler函数处理,而从wsHandler发送过来的字节,则通过onmessage事件处理函数接收,显示在textarea中。onclose处理函数在websocket中断时调用,而wsHandler中的Message.Receive在websocket中断或者出错时会返回错误,我们用它来结束for循环。 wsHandler中的Message.Receive会一直等待一个完整的websocket发送帧。也就是说,websocket不是基于字节的流传输,而是以帧Frame为单位的消息传输。最新的Chrome可以使用developer tool观察发送接收的每一个帧,非常方便。 从s返回的命令字符串,直接送到Command函数运行在窗口系统的命令行cmd下。我们重定向此命令的标准输出和标准错误输出,从websocket发送到浏览器,由onmessage事件处理函数显示在textarea中。注意io包的Copy函数会一直执行到输入EOF,所以第一个Copy我们用go放入后台执行,而第二个Copy会在前台执行到命令结束,才继续下一循环。 好了。使用go run webcmd.go编译执行此程序,打开Chome或者Safari浏览器,指向http://localhost:7224,在最下面的输入栏输入go,应该可以看到go命令说明,输入dir可以看到本目录的文件列表。我们再写个数羊的测试,sheep.go
package main
import "time"
func main() {
for i := 0; ; i++ {
time.Sleep(time.Second)
print(i)
}
}
在输入栏输入go run sheep.go, 就看到它每秒一个的数下去。
- 由dual导致的一个潜在的监控问题(r7笔记第3天)
- 剑指Offer——编程题的Java实现
- Python中if __name__ == "__main__": 的作用
- 每周算法练习——大数的乘法问题
- Java基础-25(01)图形用户界面编程GUI
- 每周算法练习——n皇后问题
- dg broker配置的问题及分析 (r7笔记第22天)
- 备库搭建中的一波三折(r7笔记第21天)
- Java基础-25(02)图形用户界面编程GUI
- 每周算法练习——最近对问题
- Java基础-25(03)图形用户界面编程GUI
- 数据结构和算法——用动态规划求解最短路径问题
- 备库报警邮件的分析案例(一) (r7笔记第14天)
- 数据结构和算法——动态规划
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP安装配置(Windows和Linux)-一篇就够了
- JavaSE面试深度剖析 第一讲
- JavaSE面试深度剖析 第二讲
- JavaSE面试深度剖析 第三讲
- docker+consul+ nginx集成分布式的服务发现与注册架构
- CWFF:一款针对模糊测试的自定义字典工具
- HMM、信号、时序、降噪(附代码)
- 原创 | 图解git,用手绘图带你理解git中分支的原理和应用
- Android 天气APP(二十四)地图天气(上)自动定位和地图点击定位
- 3分钟短文:可能是Laravel模板最直白的用法了,没有之一
- Android 天气APP(二十三)增加灾害预警、优化主页面UI
- Android 天气APP(二十一)滑动改变UI、增加更多天气数据展示,最多未来15天天气预报
- Android 读取csv格式数据文件
- Android LitePal的简单使用
- Android RecyclerVIew列表使用 (编辑、单选、全选、删除、动画效果+附源码)