最近写了一个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()) } }