go 聊天室简单版总结

/*
*    思路:在登录成功时将用户的id存进在线用户列表中的key value中链接的ws为空,并保存用户的信息.
*        当跳转到聊天室时,将用户和聊天室链接的ws存进在线用户列表中的
*        问题:如何在聊天室的页面时,获取到用户的id.可尝试在登录时存入cookie,当在聊天室页面时可以通过id来获取信息,并把当前的链接的ws存入key为用户id的ws中。若没有则代表改用户没有经过登录页面登录。
*
*/
package handler

import(
        "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)        //声明定一个在在线用户列表的map
var ch = make(chan Msg)                            //这是一个channel

type 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; }