自定义消息协议,具有很强的扩展性
package message
const (
LoginMesType = "LoginMes"
LoginResMesType = "LoginResMes"
)
type Message struct {
Type string
Data string
}
type LoginMes struct {
UserId int
UserPwd string
UserName string
}
type LoginResMes struct {
Code int
Error string
}
客户端程序使用简单的控制台命令行实现
package main
import (
"fmt"
"go_dev/chatRoom/client/login"
"os"
)
var userId int
var userPwd string
func main() {
var key int
var loop = true
for loop {
fmt.Println("----------欢迎登陆多人聊天系统--------------")
fmt.Println("\t\t\t 1 登陆聊天室")
fmt.Println("\t\t\t 2 注册用户")
fmt.Println("\t\t\t 3 退出系统")
fmt.Println("\t\t\t 请选择(1-3):")
fmt.Scanf("%d\n", &key)
switch key {
case 1:
fmt.Println("登陆聊天室")
loop = false
case 2:
fmt.Println("注册用户")
loop = false
case 3:
fmt.Println("退出系统")
os.Exit(0)
default:
fmt.Println("你的输入有误, 请重新输入")
}
}
if key == 1 {
fmt.Println("请输入用户的id")
fmt.Scanf("%d\n", &userId)
fmt.Println("请输入用户的密码")
fmt.Scanf("%d\n", &userPwd)
err := login.Login(userId, userPwd)
if err != nil {
fmt.Println("登陆失败")
} else {
fmt.Println("登陆成功")
}
} else if key == 2 {
fmt.Println("进行用户注册逻辑")
}
}
其中关键是登陆模块,有一步序列化发送的步骤
package login
import (
"encoding/binary"
"encoding/json"
"fmt"
"go_dev/chatRoom/common/message"
"net"
)
func Login(userId int, userPwd string) (err error) {
//fmt.Printf("userId = %d userPwd=%s\n", userId, userPwd)
//return nil
conn, err := net.Dial("tcp", "localhost:8889")
if err != nil {
fmt.Println("net.Dial err=", err)
return
}
// 延时关闭
var mes message.Message
mes.Type = message.LoginMesType
var loginMes message.LoginMes
loginMes.UserId = userId
loginMes.UserPwd = userPwd
data, err := json.Marshal(loginMes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
mes.Data = string(data)
data, err = json.Marshal(mes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
// 延时关闭
defer conn.Close()
var pkgLen uint32
pkgLen = uint32(len(data))
var buf [4]byte
binary.BigEndian.PutUint32(buf[0:4], pkgLen)
n, err := conn.Write(buf[:4])
if n != 4 || err != nil {
fmt.Println("conn.Write(bytes) fail", err)
return
}
fmt.Printf("客户端, 发送消息长度成功=%d", len(data))
return
}
服务器接收消息
package main
import (
"fmt"
"net"
)
func process(conn net.Conn) {
defer conn.Close()
for {
buf := make([]byte, 8096)
n, err := conn.Read(buf[:4])
if n != 4 || err != nil {
fmt.Println("conn.Read err=", err)
return
}
fmt.Println("读到的buf=", buf[:4])
}
}
func main() {
fmt.Println("服务器在8889端口监听....")
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("等待客户端来链接服务器.....")
conn, err := listen.Accept()
if err != nil {
fmt.Println("listen.Accepe err=", err)
}
go process(conn)
}
}