├── 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 ") 123 | } 124 | 125 | var err error 126 | 127 | dirPath = os.Args[1] 128 | logFile := os.Args[2] 129 | 130 | if logFp, err = os.OpenFile(logFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666); err != nil { 131 | log.Fatal("Cannot open log file: ", err.Error()) 132 | } 133 | 134 | fmt.Println("Starting...") 135 | 136 | go router() 137 | 138 | http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 139 | IndexPage(w, req, "index.html") 140 | }) 141 | 142 | http.HandleFunc("/index.js", func(w http.ResponseWriter, req *http.Request) { 143 | IndexPage(w, req, "index.js") 144 | }) 145 | 146 | http.Handle("/ws", websocket.Handler(ChatServer)) 147 | err = http.ListenAndServe(":8080", nil) 148 | if err != nil { 149 | log.Fatal("ListenAndServe: ", err) 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Chat 4 | 5 | 14 | 15 | 16 | 19 | 20 |
21 | 22 | 23 |
24 | 25 |
26 | 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | window.socket = new WebSocket("ws://" + location.host + "/ws"); 2 | 3 | function sendMessage(msg) 4 | { 5 | var len = '' + msg.length 6 | while (len.length < 5) len += ' ' 7 | socket.send(len + msg) 8 | } 9 | 10 | function handleSubmit() 11 | { 12 | var el = document.getElementById("chat-msg") 13 | sendMessage(el.value) 14 | el.value = '' 15 | 16 | return false; 17 | } 18 | 19 | function setUpSocket(onmessage) 20 | { 21 | socket.onopen = function() { 22 | console.log("Connected"); 23 | } 24 | 25 | socket.onclose = function(event) { 26 | if (event.wasClean) { 27 | console.log('Connection closed'); 28 | } else { 29 | console.log('ERROR: Connection reset'); 30 | console.log('Code: ' + event.code + ' reason: ' + event.reason); 31 | } 32 | } 33 | 34 | socket.onmessage = onmessage; 35 | 36 | socket.onerror = function(error) { 37 | console.log("Ошибка " + error.message); 38 | } 39 | } 40 | 41 | function displayMessage(msg) 42 | { 43 | var container = document.getElementById("container") 44 | 45 | var div = document.createElement("div") 46 | div.className = 'message' 47 | 48 | var textNode = document.createTextNode(msg.data); 49 | 50 | div.appendChild(textNode) 51 | container.appendChild(div) 52 | } 53 | --------------------------------------------------------------------------------