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