/** 思路:在登录成功时将用户的id存进在线用户列表中的key value中链接的ws为空,并保存用户的信息.* 当跳转到聊天室时,将用户和聊天室链接的ws存进在线用户列表中的* 问题:如何在聊天室的页面时,获取到用户的id.可尝试在登录时存入cookie,当在聊天室页面时可以通过id来获取信息,并把当前的链接的ws存入key为用户id的ws中。若没有则代表改用户没有经过登录页面登录。**/package handlerimport( "log" "net/http" "html/template" _"github.com/Go-SQL-Driver/MySQL" "database/sql" "golang.org/x/net/websocket" "time" "encoding/json")type Msg struct{ //声明一个信息类型的结构体 MsgType string MsgContent string Id string To string ClientList string ToId string}type User struct{ //声明一个用户的结构体 Id string Nickname string Password string Name string Conn *websocket.Conn}/*type OnlineUser struct{ //声明一个在线用户的结构体 Id int //这个表示key是id Conn *websocket.Conn //这个表示类型是websocket UserInfo User//这个表示类型是websocket}*/var OnlineMap = make(map[string] *User) //声明定一个在在线用户列表的mapvar ch = make(chan Msg) //这是一个channeltype Cookie struct { //设置cookie Name string Value string Path string Domain string Expires time.Time RawExpires string MaxAge int Secure bool HttpOnly bool Raw string Unparsed []string // Raw text of unparsed attribute-value pairs}func IndexHandle(w http.ResponseWriter, req * http.Request){ t,err := template.ParseFiles("./view/index.html") if err != nil{ log.Printf("no find index page") }else{ t.Execute(w, nil) } //w.Write([]byte("index")) log.Println("index")}func LoginHandle(w http.ResponseWriter, req * http.Request){ req.ParseForm() name := req.PostFormValue("name") pwd := req.PostFormValue("password") if name==""&&pwd=="" { t,_ := template.ParseFiles("./view/login.html") t.Execute(w,nil) return } var User = User{Name:name,Password:pwd} res := login(&User) if res { cookie := http.Cookie{Name: "Id", Value: User.Id, Path: "/", MaxAge: 86400} //将id 存入cookie http.SetCookie(w, &cookie) OnlineMap[User.Id] = &User urlStr := "/chat?id="+User.Id http.Redirect(w,req,urlStr,301) //301 重定向跳转 return }else{ t,_ := template.ParseFiles("./view/login.html") t.Execute(w,nil) }}func RegisterHandle(w http.ResponseWriter, req * http.Request){ err := req.ParseForm() if err != nil { log.Println(err) return } name := req.PostFormValue("name") password := req.PostFormValue("password") nickname := req.PostFormValue("nickname") res := false if name!=""&&password!=""{ var Register = User{Name:name,Password:password,Nickname:nickname} res = register(&Register) } if res { urlStr := "/login" http.Redirect(w,req,urlStr,301) //301 重定向跳转 return }else{ r,_ := template.ParseFiles("./view/register.html") r.Execute(w, nil) } if err != nil{ log.Printf("no find register page") }}type IdMsg struct{ Id string} func ChatHandle(w http.ResponseWriter, req * http.Request){ t, err := template.ParseFiles("./view/chat.html") req.ParseForm() Id := IdMsg{} if len(req.Form["id"]) > 0 { id := req.Form["id"][0] Id.Id = id _,isset := OnlineMap[id] if !isset{ http.Redirect(w,req,"/login",301) //301 重定向跳转 } }else{ http.Redirect(w,req,"/login",301) //301 重定向跳转 return; } if err != nil { return; }else{ t.Execute(w, Id) }}func Echo (ws *websocket.Conn) { var err error for { var reply Msg //user := new(OnlineUsers) if err = websocket.JSON.Receive(ws,&reply); err != nil { log.Println(err) break } client_id := reply.Id if reply.MsgType == "login"{ OnlineMap[client_id].Conn = ws OnClinetJson,_ := json.Marshal(OnlineMap) reply.ClientList = string(OnClinetJson) reply.MsgContent = OnlineMap[client_id].Name+"上线了!" ch <- reply } if reply.MsgType == "say"{ if reply.ToId == "all"{ sendMsg := OnlineMap[client_id].Nickname + " 说:" + reply.MsgContent reply.MsgContent = sendMsg ch <- reply }else{ toClientId := reply.ToId toClientWs := OnlineMap[toClientId].Conn sendMsg := OnlineMap[client_id].Nickname + " 说:" + reply.MsgContent reply.MsgContent = sendMsg SendMsg,_ := json.Marshal(reply) websocket.JSON.Send(toClientWs,string(SendMsg)) websocket.JSON.Send(ws,string(SendMsg)) } } }} //mian.go中 go run handler.SendTo()func SendTO(){ for{ select{ case a := <-ch: for _,reg := range OnlineMap{ SendMsg,_ := json.Marshal(a) websocket.JSON.Send(reg.Conn,string(SendMsg)) } } }}func SuccessHandle(w http.ResponseWriter, req * http.Request){ w.Write([]byte("success")) log.Println("success")}func ErrorHandle(w http.ResponseWriter, req * http.Request){ t, err := template.ParseFiles("./view/error.html") if err != nil { log.Printf("no find page") }else{ t.Execute(w, nil) log.Printf("find page") }}func register(register *User) (register_res bool) { db, err := sql.Open("mysql","go_test:jacky@/go_test?charset=utf8") if err != nil { return false; } name := register.Name password := register.Password nickname := register.Nickname stmt, err := db.Prepare("INSERT user SET username = ?,pwd = ?,nickname = ?") if err != nil{ return false; } _, err2 := stmt.Exec(name,password,nickname) if err2 != nil { register_res = false; }else{ register_res = true; } return register_res}func login(user *User) (res bool){ db, err := sql.Open("mysql","go_test:jacky@/go_test?charset=utf8") if err != nil{ log.Fatal(err) } name := user.Name password := user.Password stmtOut, err := db.Prepare("select id,nickname from user where username=? and pwd=?") //卧槽卧槽卧槽卧槽 【我这里写的是* 所以查出来的是一条所有的字段,】 err = stmtOut.QueryRow(name,password).Scan(&user.Id,&user.Nickname) //这里为查出来的数据赋给这个结构体,因为查出来的数据有三个字段,所以三个字段全都要在这里对应上。 if err != nil { return false; } return true;}