Golang使用websocket

1、在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 := `
              
              
                    
                    golang websocket chatroom
                    
                    
             
             
                
` 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())
    	}
}

你可能感兴趣的:(Golang使用websocket)