最近写了一个chrome的websocket extension, server端用的是Java的Netty框架, 后来发现golang 实现websocket 非常简单,高效, 下面是例子, 简单实现了用户登录,广播,相当于聊天室!- package main
- import (
- "code.google.com/p/go.net/websocket"
- "html/template"
- "log"
- "net/http"
- "os"
- "strings"
- "time"
- )
- const (
- listenAddr = "localhost:9527" // server address
- )
- var (
- pwd, _ = os.Getwd()
- RootTemp = template.Must(template.ParseFiles(pwd + "/chat.html"))
- JSON = websocket.JSON // codec for JSON
- Message = websocket.Message // codec for string, []byte
- ActiveClients = make(map[ClientConn]string) // map containing clients
- User = make(map[string]string)
- )
- // Initialize handlers and websocket handlers
- func init() {
- User["aaa"] = "aaa"
- User["bbb"] = "bbb"
- User["test"] = "test"
- User["test2"] = "test2"
- User["test3"] = "test3"
- }
- // Client connection consists of the websocket and the client ip
- type ClientConn struct {
- websocket *websocket.Conn
- clientIP string
- }
- // WebSocket server to handle chat between clients
- func SockServer(ws *websocket.Conn) {
- var err error
- var clientMessage string
- // use []byte if websocket binary type is blob or arraybuffer
- // var clientMessage []byte
- // cleanup on server side
- defer func() {
- if err = ws.Close(); err != nil {
- log.Println("Websocket could not be closed", err.Error())
- }
- }()
- client := ws.Request().RemoteAddr
- log.Println("Client connected:", client)
- sockCli := ClientConn{ws, client}
- ActiveClients[sockCli] = ""
- log.Println("Number of clients connected:", len(ActiveClients))
- // for loop so the websocket stays open otherwise
- // it'll close after one Receieve and Send
- for {
- if err = Message.Receive(ws, &clientMessage); err != nil {
- // If we cannot Read then the connection is closed
- log.Println("Websocket Disconnected waiting", err.Error())
- // remove the ws client conn from our active clients
- delete(ActiveClients, sockCli)
- log.Println("Number of clients still connected:", len(ActiveClients))
- return
- }
- var msg_arr = strings.Split(clientMessage, "|")
- if msg_arr[0] == "login" && len(msg_arr) == 3 {
- name := msg_arr[1]
- pass := msg_arr[2]
- if pass == User[name] {
- ActiveClients[sockCli] = name
- if err = Message.Send(ws, "login|"+name); err != nil {
- log.Println("Could not send message to ", client, err.Error())
- }
- } else {
- log.Println("login faild:", clientMessage)
- }
- } else if msg_arr[0] == "msg" {
- if ActiveClients[sockCli] != "" {
- clientMessage = "msg|" + time.Now().Format("2006-01-02 15:04:05") + " " + ActiveClients[sockCli] + " Said: " + msg_arr[1]
- for cs, na := range ActiveClients {
- if na != "" {
- if err = Message.Send(cs.websocket, clientMessage); err != nil {
- log.Println("Could not send message to ", cs.clientIP, err.Error())
- }
- }
- }
- }
- }
- }
- }
- // RootHandler renders the template for the root page
- func RootHandler(w http.ResponseWriter, req *http.Request) {
- err := RootTemp.Execute(w, listenAddr)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
- }
- func main() {
- http.HandleFunc("/", RootHandler)
- http.Handle("/socket", websocket.Handler(SockServer))
- err := http.ListenAndServe(listenAddr, nil)
- if err != nil {
- panic("ListenAndServe: " + err.Error())
- }
- }
有疑问加站长微信联系(非本文作者)