分享
  1. 首页
  2. 文章

Golang使用websocket

zxwbbb · · 6037 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

在Google官方维护的code.google.com\p\go.net\websocket包中的server.go文件中,曾经有这么一段描述:

// Handler is a simple interface to a WebSocket browser client.
// It checks if Origin header is valid URL by default.
// You might want to verify websocket.Conn.Config().Origin in the func.
// If you use Server instead of Handler, you could call websocket.Origin and
// check the origin in your Handshake func. So, if you want to accept
// non-browser client, which doesn't send Origin header, you could use Server
//. that doesn't check origin in its Handshake.

这里说到,Handler是一个针对Websocket浏览器客户端的简单接口,默认情况下,Handler会检查Http请求的头文件的Origin是否是一个有效的值。最后说到,如果你想接收一个并不带有Origin字段信息的非浏览器客户端发送的websocket请求,你应该使用Server,使用Server不会在Websocket握手时对Origin进行检查。

也许我们会问,什么是浏览器客户端,而什么又是非浏览器客户端,笔者对此研究的不深,只是在开发中发现,在进行go web编程时,由于go本身可以使用template模板向用户推送页面,比如用户在客户端输入127.0.0.1:9000,服务器收到这个请求,就会发送网站的首页给用户(这里假设127.0.0.1:9000的/,这个路由对应一个首页的get请求)。笔者认为凡是通过go编写的web服务端程序推送给用户的这个网页就是浏览器客户端。而除此之外的其他的非推送的网页请求,以及一些手机(andriod、ios的手机)客户端发送的请求都属于非浏览器客户端。

那我们又会问,如果是浏览器客户端,该如何使用Handler,而非浏览器客户端,该如何使用Server呢?下面就简单举例说一下:

先说浏览器客户端的监听websocket编程的写法,代码实例为:

package main

import (
"bufio"
"code.google.com/p/go.net/websocket"
"container/list"
"fmt"
"io"
"net/http"
)

var connid int
var conns *list.List

func ChatroomServer(ws *websocket.Conn) {
defer ws.Close()

connid++
id := connid

fmt.Printf("connection id: %d\n", id)

item := conns.PushBack(ws)
conns.Remove(item)

name := fmt.Sprintf("user%d", id)

SendMessage(nil, fmt.Sprintf("welcome %s join\n", name))

r := bufio.NewReader(ws)

for {
data, err := r.ReadBytes('\n')
if err != nil {
fmt.Printf("disconnected id: %d\n", id)
SendMessage(item, fmt.Sprintf("%s offline\n", name))
break
}

fmt.Printf("%s: %s", name, data)

SendMessage(item, fmt.Sprintf("%s\t> %s", name, data))
}
}

func SendMessage(self *list.Element, data string) {
for item := conns.Front(); item != nil; item = item.Next() {
ws, ok := item.Value.(*websocket.Conn)
if !ok {
panic("item not *websocket.Conn")
}

if item == self {
continue
}

io.WriteString(ws, data)
}
}

func Client(w http.ResponseWriter, r *http.Request) {
html := `<!doctype html>

 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <title>golang websocket chatroom</title>
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
 <script>
 var ws = new WebSocket("ws://127.0.0.1:6611/chatroom");
 ws.onopen = function(e){
 console.log("onopen");
 console.dir(e);
 };
 ws.onmessage = function(e){
 console.log("onmessage");
 console.dir(e);
 $('#log').append('<p>'+e.data+'<p>');
 $('#log').get(0).scrollTop = $('#log').get(0).scrollHeight;
 };
 ws.onclose = function(e){
 console.log("onclose");
 console.dir(e);
 };
 ws.onerror = function(e){
 console.log("onerror");
 console.dir(e);
 };
 $(function(){
 $('#msgform').submit(function(){
 ws.send($('#msg').val()+"\n");
 $('#log').append('<p style="color:red;">My > '+$('#msg').val()+'<p>');
 $('#log').get(0).scrollTop = $('#log').get(0).scrollHeight;
 $('#msg').val('');
 return false;
 });
 });
 </script>
 </head>
 <body>
 <div id="log" style="height: 300px;overflow-y: scroll;border: 1px solid #CCC;"></div>
 <div>
 <form id="msgform">
 <input type="text" id="msg" size="60" />
 </form>
 </div>
 </body>
 </html>`

io.WriteString(w, html)
}

func main() {
fmt.Printf(`Welcome chatroom server! `)

connid = 0
conns = list.New()

http.Handle("/chatroom", websocket.Handler(ChatroomServer))
http.HandleFunc("/", Client)
err := http.ListenAndServe(":9090", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}

以上是一个完整的针对浏览器客户端发送websocket的服务器代码,可以看到,当用户请求路由为/时,服务器推送一个页面给用户,这个页面含有websocket套接字,然后收到这个页面的用户,就可以在这个页面是输入信息发往后台,发送时使用的就是websocket。main函数中展示了如何使用websocket.Handler.

下面说一下非浏览器客户端的写法,这里只修改了main函数,为了能够同时监听http请求和websocket请求,与上面不同,这里使用了多协程的方式实现,同时这里的websocket监听无须路由,所有的websocket,无论路由是多少,都将被监听到,代码如下:

func main() {
fmt.Printf(`Welcome chatroom server! `)

connid = 0
conns = list.New()

http.HandleFunc("/", Client)

go func(){

err := http.ListenAndServe(":9090", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}

}
err := http.ListenAndServe(":9090", websocket.Server{websocket.Config{},nil,ChatroomServer})
if err != nil {
panic("ListenAndServe: " + err.Error())
}

}

完结


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:zxwbbb

查看原文:Golang使用websocket

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
6037 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏