Golang使用websocket

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

在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())
    }

}

 

完結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.