golang 客户端服务端登录

client/login.go

package main

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	"testgo/chatrroom/common/message"
)

func login(userId int, userPwd string) (err error) {
	//开始定协议

	//fmt.Println("userId = %d,userPwd = %d", userId, userPwd)
	//return nil

	//1.连接服务器
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err", err)
		return
	}
	//延时关闭
	defer conn.Close()
	//2.准备通过coon发送消息给服务
	var mes message.Message
	mes.Type = message.LoginMesType
	//创建一个LoginMes结构体
	var loginMes message.LoginMes
	loginMes.UserId = userId
	loginMes.UserPwd = userPwd
	//4.将loginMes序列化
	data, err := json.Marshal(loginMes)
	if err != nil {
		fmt.Println("json.Marshal err", err)
		return
	}
	//5.把data给mes.Data字段
	mes.Data = string(data)
	//6.将mes序列化
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("json.Marshal err", err)
		return
	}
	//7. data就是我们要发送的东西
	//7.1 先把data长度发送给服务器
	//先获取data的长度,转化byte切片
	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("coon.Write", err)
		return
	}
	//fmt.Println("客户端,发送消息的长度成功 内容=%s", len(data), string(data))
	//发送信息本身
	_, err = conn.Write(data)
	if err != nil {
		fmt.Println("coon.Write(data)", err)
		return
	}
	//time.Sleep(2 * time.Second)
	//fmt.Println("休眠了2...")
	//还需要处理服务端
	mes, err = readPkg(conn)
	//将mes的data部分反序列化成 LoginResMes
	if err != nil {
		fmt.Println("readPkg(conn) err=", err)
		return
	}
	//将mes的data部分反序列化成LoginresMes
	var loginResMes message.LoginResMes
	err = json.Unmarshal([]byte(mes.Data), &loginResMes)
	if loginResMes.Code == 200 {
		fmt.Println("登录成功")
	} else if loginResMes.Code == 500 {
		fmt.Println(loginResMes.Error)
	}
	return
}

client/main.go

package main

import (
	"fmt"
	"os"
)

//定义两个变量 用户id 用户密码

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.Scanln(&userId)
		fmt.Println("请输入用户密码")
		fmt.Scanln(&userPwd)
		//先把登录的函数,写到另一个文件
		login(userId, userPwd)
		//if err != nil {
		//	fmt.Println("登录失败")
		//} else {
		//	fmt.Println("登录成功")
		//}
	} else if key == 2 {
		fmt.Println("进行用户注册")
	}
}

cilent/utils.go

package main

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	"testgo/chatrroom/common/message"
)

func readPkg(conn net.Conn) (mes message.Message, err error) {
	buf := make([]byte, 8096)
	fmt.Println("读取客户端发送信息...")
	//在conn没有被关闭的情况下,才会阻塞
	_, err = conn.Read(buf[:4])
	if err != nil {
		//	err = errors.New("read pkg header error")
		return
	}
	//fmt.Println("读到的buf=", buf[:4])
	var pkgLen uint32
	pkgLen = binary.BigEndian.Uint32(buf[0:4])

	//根据pkgLen读取消息内容
	n, err := conn.Read(buf[:pkgLen])
	if n != int(pkgLen) || err != nil {
		//err = errors.New(" conn.Read error")
		return
	}
	// 把pkgLen 反序列化 ->message.Message
	err = json.Unmarshal(buf[:pkgLen], &mes)
	if err != nil {
		fmt.Println("json.Unmarshal err=", err)
		return
	}
	return
}
func writePkg(conn net.Conn, data []byte) (err error) {
	//先发送一个长度给对方
	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 err=", err)
		return
	}
	//序列化
	n, err = conn.Write(data)
	if n != int(pkgLen) || err != nil {
		fmt.Println("conn.Write(bytes) fail", err)
		return
	}
	//发送消息本身
	err = writePkg(conn, data)
	return err
}

common/message/message.go

package message

const (
	LoginMesType    = "LoginMes"
	LoginResMesType = "LoginResMes"
	RegisterMesType = "RegisterMes"
)

type Message struct {
	Type string `json:"type"` //消息类型
	Data string `json:"data"` //消息的类型
}

// LoginMes 定义两个消息
type LoginMes struct {
	UserId   int    `json:"userId"`   //用户id
	UserPwd  string `json:"userPwd"`  //用户密码
	UserName string `json:"userName"` //用户名
}

type LoginResMes struct {
	Code  int    `json:"code"`  //状态码
	Error string `json:"error"` //返回错误信息
}

type RegisterMes struct {
	//...
}

server/main.go

package main

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"testgo/chatrroom/common/message"
)

func readPkg(conn net.Conn) (mes message.Message, err error) {
	buf := make([]byte, 8096)
	fmt.Println("读取客户端发送信息...")
	//在conn没有被关闭的情况下,才会阻塞
	_, err = conn.Read(buf[:4])
	if err != nil {
		//	err = errors.New("read pkg header error")
		return
	}
	//fmt.Println("读到的buf=", buf[:4])
	var pkgLen uint32
	pkgLen = binary.BigEndian.Uint32(buf[0:4])

	//根据pkgLen读取消息内容
	n, err := conn.Read(buf[:pkgLen])
	if n != int(pkgLen) || err != nil {
		//err = errors.New(" conn.Read error")
		return
	}
	// 把pkgLen 反序列化 ->message.Message
	err = json.Unmarshal(buf[:pkgLen], &mes)
	if err != nil {
		fmt.Println("json.Unmarshal err=", err)
		return
	}
	return
}
func writePkg(conn net.Conn, data []byte) (err error) {
	//先发送一个长度给对方
	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 err=", err)
		return
	}
	//发送data本身
	n, err = conn.Write(data)
	if n != int(pkgLen) || err != nil {
		fmt.Println("conn.Write(bytes) fail", err)
		return
	}
	return
}

//编写一个serverProcessLogin函数 处理登录请求
func serverProcessLogin(conn net.Conn, mes *message.Message) (err error) {
	//核心代码
	//1.从mes 中取出mes.data 反序列化为loginMes
	var loginMes message.LoginMes
	err = json.Unmarshal([]byte(mes.Data), &loginMes)
	if err != nil {
		fmt.Println("json.Unmarshal fail err=", err)
		return
	}
	//声明一个resMes
	var resMes message.Message
	resMes.Type = message.LoginResMesType
	//声明 LoginResMes
	var loginResMes message.LoginResMes
	if loginMes.UserId == 100 && loginMes.UserPwd == "123456" {
		loginResMes.Code = 200
	} else {
		loginResMes.Code = 500
		loginResMes.Error = "用户不存在,请重新注册"
	}
	//3.将loginResMes序列化
	data, err := json.Marshal(loginResMes)
	if err != nil {
		fmt.Println("json.marshal err=", err)
		return
	}
	//4.将data赋值给resMes
	resMes.Data = string(data)
	//5.对resMes序列化
	data, err = json.Marshal(resMes)
	if err != nil {
		fmt.Println("json.marshal err=", err)
		return
	}
	//3.发送data
	err = writePkg(conn, data)
	return err
}

//编写一个serverProcessMes函数
//根据客户端发送信息种类不同,决定调用那个函数处理
func serverProcessMes(conn net.Conn, mes *message.Message) (err error) {
	switch mes.Type {
	case message.LoginMesType:
		//处理登录
		err = serverProcessLogin(conn, mes)
	case message.RegisterMesType:
	//处理注册
	default:
		fmt.Println("消息类型不存在,无法处理")
	}
	return
}
func process(conn net.Conn) {
	//读取客户端发送的信息
	defer conn.Close()
	//循环读取
	for {
		//读取数据包,直接封装成一个函数readPKG(),返回,Message,err
		mes, err := readPkg(conn)
		if err != nil {
			if err == io.EOF {
				fmt.Println("客户端退出,服务端也退出")
				return
			} else {
				fmt.Println("readPkg(conn) err=", err)
				return
			}
		}
		//fmt.Println("message=", mes)
		err = serverProcessMes(conn, &mes)
		if err != nil {
			return
		}
	}
}
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 err=", err)
		}

		//一旦连接成功,则启动一个协程和客户端保持通讯..
		go process(conn)
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值