The whole project uses MVC mode, CS architecture, transmission layer based on TCP protocol, application layer based on custom protocol, and developed with Go language. The project has strong expansibility.
Server master function
func main() { initPool("localhost:6379", 16, 0, 300*time.Second) initUserDao() fmt.Println("The server listens on the new 8889 port....") listen, err := net.Listen("tcp", "0.0.0.0:8889") defer listen.Close() if err != nil { fmt.Println("net.Listen err=", err) return } for { fmt.Println("Wait for client to link server.....") conn, err := listen.Accept() if err != nil { fmt.Println("listen.Accepe err=", err) } go process(conn) } }
The main function initializes the database connection pool and the module UserDao, which deals with the interaction with the database.
func process(conn net.Conn) { defer conn.Close() processor := &Processor{ Conn: conn, } processor.process2() } func initUserDao() { model.MyUserDao = model.NewUserDao(pool) }
Each client corresponds to a process, and each process executes the process function.
Process establishes a processor function for each client to process business logic
func (this *Processor) process2() { for { tf := &utils.Transfer{ Conn: this.Conn, } mes, err := tf.ReadPkg() if err != nil { if err == io.EOF { fmt.Println("process2()Error in") fmt.Println("Client exit, The server also exits..") return } else { fmt.Println("process2()Error in") fmt.Println("readPkg err=", err) return } } fmt.Println("mes=", mes) err = this.serverProcessMes(&mes) if err != nil { fmt.Println("serverProcessMes err") return } } }
Then we can see that there are currently two server modules: login and registration.
func (this *Processor) serverProcessMes(mes *message.Message) (err error) { switch mes.Type { case message.LoginMesType: // Handling landing up := &process2.UserProcess{ Conn: this.Conn, } err = up.ServerProcessLogin(mes) case message.RegisterMesType: // Processing registration up := &process2.UserProcess{ Conn: this.Conn, } err = up.ServerProcessRegister(mes) default: fmt.Println("Message type does not exist, Unable to deal with...") } return }
These two are processed through the UserProcess module.
There are functions to handle login and registration in UserProcess
Handling registered functions
func (this *UserProcess) ServerProcessRegister(mes *message.Message) (err error) { var registerMes message.RegisterMes err = json.Unmarshal([]byte(mes.Data), ®isterMes) if err != nil { fmt.Println("json.Unmarshall fail err=", err) return } // A resMes var resMes message.Message resMes.Type = message.RegisterResMesType var registerResMes message.RegisterResMes err = model.MyUserDao.Register(®isterMes.User) if err != nil { if err == model.ERROR_USER_EXISTS { registerResMes.Code = 505 registerResMes.Error = err.Error() } else { registerResMes.Code = 506 registerResMes.Error = "Unknown error registering" } } else { registerResMes.Code = 200 } // Serialize loginResMes data, err := json.Marshal(registerResMes) if err != nil { fmt.Println("json.Marshal fail", err) return } // Assign data to resMes resMes.Data = string(data) // Serialize resMes and prepare to send data, err = json.Marshal(resMes) if err != nil { fmt.Println("json.Marshal fail", err) return } tf := &utils.Transfer{ Conn: this.Conn, } err = tf.WritePkg(data) return }
Functions for handling login
func (this *UserProcess) ServerProcessLogin(mes *message.Message) (err error) { var loginMes message.LoginMes err = json.Unmarshal([]byte(mes.Data), &loginMes) if err != nil { fmt.Println("json.Unmarshall fail err=", err) return } // A resMes var resMes message.Message resMes.Type = message.LoginResMesType // Declaring a LoginResMes var loginResMes message.LoginResMes //fmt.Println(loginMes.UserId) user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd) if err != nil { if err == model.ERROR_USER_NOTEXISTS { loginResMes.Code = 500 loginResMes.Error = err.Error() } else if err == model.ERROR_USER_PWD { loginResMes.Code = 403 loginResMes.Error = err.Error() } else { loginResMes.Code = 505 loginResMes.Error = "Server internal error..." } } else { loginResMes.Code = 200 fmt.Println(user, "Landing successfully") } // Serialize loginResMes data, err := json.Marshal(loginResMes) if err != nil { fmt.Println("json.Marshal fail", err) return } // Assign data to resMes resMes.Data = string(data) // Serialize resMes and prepare to send data, err = json.Marshal(resMes) if err != nil { fmt.Println("json.Marshal fail", err) return } tf := &utils.Transfer{ Conn: this.Conn, } err = tf.WritePkg(data) return }
The interaction between data and database is completed through userDao.
Landing function
func (this *UserDao) Login(userId int, userPwd string) (user *User, err error) { conn := this.pool.Get() defer conn.Close() user, err = this.getUserById(conn, userId) //fmt.Println(string(user.UserId)) if err != nil { return } if user.UserPwd != userPwd { err = ERROR_USER_PWD return } return }
Register function
func (this *UserDao) Register(user *message.User) (err error) { conn := this.pool.Get() defer conn.Close() _, err = this.getUserById(conn, user.UserId) if err == nil { err = ERROR_USER_EXISTS return } // At this time, if the id is not in redis, you can complete the registration. data, err := json.Marshal(user) if err != nil { return } _, err = conn.Do("HSet", "users", user.UserId, string(data)) if err != nil { fmt.Println("Error saving registered user err=", err) return } return }