当前位置:网站首页>golang 客户端服务端登录
golang 客户端服务端登录
2022-07-07 15:48:00 【一只泰迪熊】
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)
}
}
边栏推荐
- Native JS verification code
- Mobile pixel bird game JS play code
- Create dialog style windows with popupwindow
- 第2章搭建CRM项目开发环境(搭建开发环境)
- Deep learning machine learning various data sets summary address
- 使用 xml资源文件定义菜单
- 企业经营12法的领悟
- What skills can you master to be a "master tester" when doing software testing?
- 本周小贴士#134:make_unique与私有构造函数
- Face recognition attendance system based on Baidu flying plasma platform (easydl)
猜你喜欢
![[OKR target management] value analysis](/img/d9/1f0022d3aa34cc10f1151e181dd695.png)
[OKR target management] value analysis

viewflipper的功能和用法

Mrs offline data analysis: process OBS data through Flink job

toast会在程序界面上显示一个简单的提示信息

datepicket和timepicket,日期、时间选择器的功能和用法

Test for 3 months, successful entry "byte", my interview experience summary

第3章业务功能开发(用户登录)

【重新理解通信模型】Reactor 模式在 Redis 和 Kafka 中的应用

js拉下帷幕js特效显示层

Target detection 1 -- actual operation of Yolo data annotation and script for converting XML to TXT file
随机推荐
Youth experience and career development
[answer] if the app is in the foreground, the activity will not be recycled?
[distributed theory] (I) distributed transactions
【解惑】App处于前台,Activity就不会被回收了?
Mrs offline data analysis: process OBS data through Flink job
USB通信协议深入理解
第3章业务功能开发(实现记住账号密码)
yolo训练过程中批量导入requirments.txt中所需要的包
[OKR target management] value analysis
Yarn capacity scheduler (ultra detailed interpretation)
自动化测试:Robot FrameWork框架大家都想知道的实用技巧
[4500 word summary] a complete set of skills that a software testing engineer needs to master
Use seven methods to enhance all the images in a folder
actionBar 导航栏学习
运行yolo v5-5.0版本报错找不到SPPF错误,进行解决
viewflipper的功能和用法
serachview的功能和用法
Import requirements in batches during Yolo training Txt
How to implement safety practice in software development stage
Threshold segmentation based on RGB image and threshold adjustment by sliding