├── main.go └── src ├── index.html └── index.js /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "code.google.com/p/go.net/websocket" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net/http" 9 | "os" 10 | "strconv" 11 | "strings" 12 | ) 13 | 14 | type ( 15 | Msg struct { 16 | clientKey string 17 | text string 18 | } 19 | 20 | NewClientEvent struct { 21 | clientKey string 22 | msgChan chan *Msg 23 | } 24 | ) 25 | 26 | var ( 27 | dirPath string 28 | logFp *os.File 29 | clientRequests = make(chan *NewClientEvent, 100) 30 | clientDisconnects = make(chan string, 100) 31 | messages = make(chan *Msg, 100) 32 | ) 33 | 34 | func IndexPage(w http.ResponseWriter, req *http.Request, filename string) { 35 | fp, err := os.Open(dirPath + "/" + filename) 36 | if err != nil { 37 | log.Println("Could not open file", err.Error()) 38 | w.Write([]byte("500 internal server error")) 39 | return 40 | } 41 | 42 | defer fp.Close() 43 | 44 | _, err = io.Copy(w, fp) 45 | if err != nil { 46 | log.Println("Could not send file contents", err.Error()) 47 | w.Write([]byte("500 internal server error")) 48 | return 49 | } 50 | } 51 | 52 | func ChatServer(ws *websocket.Conn) { 53 | lenBuf := make([]byte, 5) 54 | 55 | msgChan := make(chan *Msg, 100) 56 | clientKey := ws.RemoteAddr().String() 57 | clientRequests <- &NewClientEvent{clientKey, msgChan} 58 | defer func() { clientDisconnects <- clientKey }() 59 | 60 | go func() { 61 | for msg := range msgChan { 62 | ws.Write([]byte(msg.text)) 63 | } 64 | }() 65 | 66 | for { 67 | _, err := ws.Read(lenBuf) 68 | if err != nil { 69 | log.Println("Error: ", err.Error()) 70 | return 71 | } 72 | 73 | length, _ := strconv.Atoi(strings.TrimSpace(string(lenBuf))) 74 | if length > 65536 { 75 | log.Println("Error: too big length: ", length) 76 | return 77 | } 78 | 79 | if length <= 0 { 80 | log.Println("Empty length: ", length) 81 | return 82 | } 83 | 84 | buf := make([]byte, length) 85 | _, err = ws.Read(buf) 86 | 87 | if err != nil { 88 | log.Println("Could not read ", length, " bytes: ", err.Error()) 89 | return 90 | } 91 | 92 | messages <- &Msg{clientKey, string(buf)} 93 | } 94 | } 95 | 96 | func router() { 97 | clients := make(map[string]chan *Msg) 98 | 99 | for { 100 | select { 101 | case req := <-clientRequests: 102 | clients[req.clientKey] = req.msgChan 103 | log.Println("Websocket connected: " + req.clientKey) 104 | case clientKey := <-clientDisconnects: 105 | close(clients[clientKey]) 106 | delete(clients, clientKey) 107 | log.Println("Websocket disconnected: " + clientKey) 108 | case msg := <-messages: 109 | logFp.WriteString(msg.clientKey + ": " + msg.text + "\n") 110 | 111 | for _, msgChan := range clients { 112 | if len(msgChan) < cap(msgChan) { 113 | msgChan <- msg 114 | } 115 | } 116 | } 117 | } 118 | } 119 | 120 | func main() { 121 | if len(os.Args) < 3 { 122 | log.Fatal("Usage: chatExample