go 聊天室

发布时间 2023-12-12 10:48:30作者: HHMLXL

main.go

  1 package main
  2 
  3 import (
  4     "encoding/json"
  5     "fmt"
  6     "net/http"
  7 
  8     "github.com/gorilla/websocket"
  9     "github.com/gorilla/mux"
 10 )
 11 
 12 type Data struct {
 13     Ip string `json:"ip"`
 14     User string `json:"user"`
 15     From string `json:"from"`
 16     Type string `json:"type"`
 17     Content string `json:"content"`
 18     UserList []string `json:"user_list"`
 19 }
 20 
 21 type connection struct {
 22     ws *websocket.Conn
 23     sc chan []byte
 24     data *Data
 25 }
 26 
 27 type hub struct {
 28     c map[*connection]bool
 29     b chan []byte
 30     r chan *connection
 31     u chan *connection
 32 }
 33 
 34 var h = hub{
 35     c: make(map[*connection]bool),
 36     b: make(chan []byte),
 37     r: make(chan *connection),
 38     u: make(chan *connection),
 39 }
 40 
 41 func (h *hub) run(){
 42     for {
 43         select {
 44         case c:= <-h.r:
 45             h.c[c] = true
 46             c.data.Ip = c.ws.RemoteAddr().String()
 47             c.data.Type = "handshake"
 48             c.data.UserList = user_list
 49             data_b, _ := json.Marshal(c.data)
 50             c.sc <- data_b
 51         case c:= <-h.u:
 52             fmt.Println(h.u)
 53             if _, ok := h.c[c]; ok {
 54                 delete(h.c, c)
 55                 close(c.sc)
 56             }
 57         case data := <-h.b:
 58             for c := range h.c {
 59                 select {
 60                 case c.sc <- data:
 61                 default:
 62                     delete(h.c, c)
 63                     close(c.sc)
 64                 }
 65             }
 66         }
 67     }
 68 }
 69 
 70 var wu = &websocket.Upgrader{ReadBufferSize:512,
 71     WriteBufferSize: 512, CheckOrigin: func(r *http.Request) bool { return true }}
 72 
 73 func myws(w http.ResponseWriter, r *http.Request) {
 74     ws, err := wu.Upgrade(w, r, nil)
 75     if err != nil {
 76         return
 77     }
 78     c := &connection{sc: make(chan []byte, 256), ws: ws, data: &Data{}}
 79     h.r <- c
 80     go c.writer()
 81     c.reader()
 82     defer func() {
 83     
 84         c.data.Type = "logout"
 85         user_list = del(user_list, c.data.User)
 86         c.data.UserList = user_list
 87         c.data.Content = c.data.User
 88         data_b, _ := json.Marshal(c.data)
 89         h.b <- data_b
 90         h.r <- c
 91     }()
 92 }
 93 
 94 func (c *connection) writer() {
 95     for message := range c.sc {
 96         c.ws.WriteMessage(websocket.TextMessage, message)
 97     }
 98     c.ws.Close()
 99 }
100 
101 var user_list = []string{}
102 
103 func (c *connection) reader() {
104     for {
105         _, message, err := c.ws.ReadMessage()
106         if err != nil {
107             h.r <- c
108             break
109         }
110         json.Unmarshal(message, &c.data)
111         switch c.data.Type {
112         case "login":
113             c.data.User = c.data.Content
114             c.data.From = c.data.User
115             user_list = append(user_list, c.data.User)
116             c.data.UserList = user_list
117             data_b, _ := json.Marshal(c.data)
118             h.b <- data_b
119         case "user":
120             c.data.Type = "user"
121             data_b, _ := json.Marshal(c.data)
122             h.b <- data_b
123         case "logout":
124             c.data.Type = "logout"
125             user_list = del(user_list, c.data.User)
126             data_b, _ := json.Marshal(c.data)
127             h.b <- data_b
128             h.r <- c
129         default:
130             fmt.Print("========default================")
131         }
132     }
133 }
134 
135 func del(slice []string, user string) []string {
136     count := len(slice)
137     if count == 0 {
138         return slice
139     }
140     if count == 1 && slice[0] == user {
141         return []string{}
142     }
143     var n_slice = []string{}
144     for i := range slice {
145         if slice[i] == user && i == count {
146             return slice[:count]
147         } else if slice[i] == user {
148             n_slice = append(slice[:i], slice[i+1:]...)
149             break
150         }
151     }
152     fmt.Println(n_slice)
153     return n_slice
154 }    
155 
156 
157 func main() {
158     router := mux.NewRouter()
159     go h.run()
160     router.HandleFunc("/ws", myws)
161     if err := http.ListenAndServe("127.0.0.1:8080", router); err != nil {
162         fmt.Println("err:", err)
163     }
164 }

 

local.html

 

  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <title></title>
  5     <meta http-equiv="content-type" content="text/html;charset=utf-8">
  6     <style>
  7         p {
  8             text-align: left;
  9             padding-left: 20px;
 10         }
 11     </style>
 12 </head>
 13 <body>
 14 <div style="width: 800px;height: 600px;margin: 30px auto;text-align: center">
 15     <h1>www.5lmh.comy演示聊天室</h1>
 16     <div style="width: 800px;border: 1px solid gray;height: 300px;">
 17         <div style="width: 200px;height: 300px;float: left;text-align: left;">
 18             <p><span>当前在线:</span><span id="user_num">0</span></p>
 19             <div id="user_list" style="overflow: auto;">
 20             </div>
 21         </div>
 22         <div id="msg_list" style="width: 598px;border:  1px solid gray; height: 300px;overflow: scroll;float: left;">
 23         </div>
 24     </div>
 25     <br>
 26     <textarea id="msg_box" rows="6" cols="50" onkeydown="confirm(event)"></textarea><br>
 27     <input type="button" value="发送" onclick="send()">
 28 </div>
 29 </body>
 30 </html>
 31 <script type="text/javascript">
 32     var uname = prompt('请输入用户名', 'user' + uuid(8, 16));
 33     var ws = new WebSocket("ws://127.0.0.1:8080/ws");
 34     ws.onopen = function () {
 35         var data = "系统消息:建立连接成功";
 36         listMsg(data);
 37     };
 38     ws.onmessage = function (e) {
 39         console.log(e.data)
 40         console.log(e)
 41         
 42         var msg = JSON.parse(e.data);
 43         var sender, user_name, name_list, change_type;
 44         switch (msg.type) {
 45             case 'system':
 46                 sender = '系统消息: ';
 47                 break;
 48             case 'user':
 49                 sender = msg.from + ': ';
 50                 break;
 51             case 'handshake':
 52                 var user_info = {'type': 'login', 'content': uname};
 53                 sendMsg(user_info);
 54                 return;
 55             case 'login':
 56             case 'logout':
 57                 user_name = msg.content;
 58                 name_list = msg.user_list;
 59                 change_type = msg.type;
 60                 dealUser(user_name, change_type, name_list);
 61                 return;
 62         }
 63         var data = sender + msg.content;
 64         listMsg(data);
 65     };
 66     ws.onerror = function () {
 67         var data = "系统消息 : 出错了,请退出重试.";
 68         listMsg(data);
 69     };
 70     function confirm(event) {
 71         var key_num = event.keyCode;
 72         if (13 == key_num) {
 73             send();
 74         } else {
 75             return false;
 76         }
 77     }
 78     function send() {
 79         var msg_box = document.getElementById("msg_box");
 80         var content = msg_box.value;
 81         var reg = new RegExp("\r\n", "g");
 82         content = content.replace(reg, "");
 83         var msg = {'content': content.trim(), 'type': 'user'};
 84         sendMsg(msg);
 85         msg_box.value = '';
 86     }
 87     function listMsg(data) {
 88         var msg_list = document.getElementById("msg_list");
 89         var msg = document.createElement("p");
 90         msg.innerHTML = data;
 91         msg_list.appendChild(msg);
 92         msg_list.scrollTop = msg_list.scrollHeight;
 93     }
 94     function dealUser(user_name, type, name_list) {
 95         var user_list = document.getElementById("user_list");
 96         var user_num = document.getElementById("user_num");
 97         while(user_list.hasChildNodes()) {
 98             user_list.removeChild(user_list.firstChild);
 99         }
100         for (var index in name_list) {
101             var user = document.createElement("p");
102             user.innerHTML = name_list[index];
103             user_list.appendChild(user);
104         }
105         user_num.innerHTML = name_list.length;
106         user_list.scrollTop = user_list.scrollHeight;
107         var change = type == 'login' ? '上线' : '下线';
108         var data = '系统消息: ' + user_name + '' + change;
109         listMsg(data);
110     }
111     function sendMsg(msg) {
112         var data = JSON.stringify(msg);
113         ws.send(data);
114     }
115     function uuid(len, radix) {
116         var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
117         var uuid = [], i;
118         radix = radix || chars.length;
119         if (len) {
120             for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
121         } else {
122             var r;
123             uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
124             uuid[14] = '4';
125             for (i = 0; i < 36; i++) {
126                 if (!uuid[i]) {
127                     r = 0 | Math.random() * 16;
128                     uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
129                 }
130             }
131         }
132         return uuid.join('');
133     }
134 </script>
View Code