简单即时通讯
客户端输入用户名和密码
服务器验证用户名和密码,验证成功返回给客户端
- 定义协议 message.go
package message
var (
LoginMesType = "LoginMes"
LoginResMesType = "LoginResMes"
)
//登录协议
type LoginMes struct {
UserId int `json:"user_id"`
UserPwd string `json:"user_pwd"`
UserName string `json:"user_name"`
}
//发送协议
type Message struct {
Type string `json:"type"`
Data string `json:"data"`
}
//返回协议
type LoginResMes struct {
Code string `json:"code"`
Error string `json:"error"`
}
客户端
login.go
package main
import (
"chat/common/message"
"encoding/binary"
"encoding/json"
"fmt"
"net"
)
//接受
func readPkg(conn net.Conn) (mes message.Message, err error) {
buf := make([]byte, 8096)
fmt.Println("读取客户端发送的数据")
//第一次读
_, err = conn.Read(buf[:4]) //读4个
if err != nil {
fmt.Println("Read err=", err)
return
}
//fmt.Println("服务器读到的n=", n)
//buf[:4]转一个uint32
var pkgLen uint32
pkgLen = binary.BigEndian.Uint32(buf[0:4])
//第二次读
n, err := conn.Read(buf[:pkgLen])
if n != int(pkgLen) || err != nil {
return
}
err = json.Unmarshal(buf[:pkgLen], &mes)
if err != nil {
fmt.Println("json.Unmarshal(buf[0:pkgLen],&mes) err=", err)
return
}
return
}
//发送
func Write(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[0:4])
if err != nil {
fmt.Println("conn.Write(buf[0:4]) err=", err)
return
}
//发送内容
n, err = conn.Write(data)
if n != int(pkgLen) || err != nil {
fmt.Println("conn.Write(data) err=", err)
return
}
return
}
func login(userId int, userPwd string) (err error) {
conn, err := net.Dial("tcp", "127.0.0.1:8899")
if err != nil {
fmt.Println("64=>连接错误,err=", err)
}
defer conn.Close()
//2准备跳过conn发送消息给服务器
var loginMes message.LoginMes
loginMes.UserId = userId
loginMes.UserPwd = userPwd
data, err := json.Marshal(loginMes)
if err != nil {
fmt.Println("line 55=>json.Marshal(loginMes) err =", err)
return
}
var mes message.Message
mes.Type=message.LoginMesType
mes.Data = string(data) //把data赋值给mes.Data
data, err = json.Marshal(mes)
fmt.Println(data)
if err != nil {
fmt.Println("line 55=>json.Marshal(loginMes) err =", err)
return
}
//import "encoding/binary"
//binary包实现了简单的数字与字节序列的转换以及变长值的编解码。
var pkgLen uint32
pkgLen = uint32(len(data))
var buf [4]byte
//func (bigEndian) PutUint32(b []byte, v uint32) {
//参数v 是uint32类型的值
binary.BigEndian.PutUint32(buf[0:4], pkgLen)
//buf[0:4] [0 0 0 48]
_, err = conn.Write(buf[0:4])
if err != nil {
fmt.Println("80line 发送长度失败 err=", err)
return
}
fmt.Printf("客户端,发送消息的长度=%d,内容为%s", len(data), string(data))
_, err = conn.Write(data)
if err != nil {
fmt.Println("80line 发送长度失败 err=", err)
return
}
//读服务器返回的信息
mes ,err = readPkg(conn)
fmt.Println("读取到服务器返回数据==",mes)
if err != nil {
fmt.Println(" readPkg(conn) err=",err)
}
fmt.Println("mes=",mes)
var LoginResMes message.LoginResMes
err =json.Unmarshal([]byte(mes.Data),&LoginResMes)
if err != nil {
fmt.Println(" json.Unmarshal([]byte(mes.Data),&LoginResMes) err=",err)
}
if LoginResMes.Code == "200" {
fmt.Println("登录成功~~~哈哈")
}
return
}
server.go
package main
import (
"chat/common/message"
"encoding/binary"
"encoding/json"
"fmt"
"io"
"net"
)
//接受
func readPkg(conn net.Conn) (mes message.Message, err error) {
buf := make([]byte, 8096)
fmt.Println("读取客户端发送的数据")
//第一次读
_, err = conn.Read(buf[:4]) //读4个
if err != nil {
fmt.Println("Read err=", err)
return
}
//fmt.Println("服务器读到的n=", n)
//buf[:4]转一个uint32
var pkgLen uint32
pkgLen = binary.BigEndian.Uint32(buf[0:4])
//第二次读
n, err := conn.Read(buf[:pkgLen])
if n != int(pkgLen) || err != nil {
return
}
err = json.Unmarshal(buf[:pkgLen], &mes)
if err != nil {
fmt.Println("json.Unmarshal(buf[0:pkgLen],&mes) err=", err)
return
}
return
}
//发送
func Write(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[0:4])
if err != nil {
fmt.Println("conn.Write(buf[0:4]) err=", err)
return
}
//发送内容
n, err = conn.Write(data)
if n != int(pkgLen) || err != nil {
fmt.Println("conn.Write(data) err=", err)
return
}
return
}
//处理和客户端的通讯
func process(conn net.Conn) {
//延时关闭
defer conn.Close()
for {
fmt.Println("客户端连接........")
mes, err := readPkg(conn)
if err != nil {
if err == io.EOF {
fmt.Println("客户端退出,服务器也退出")
return
} else {
fmt.Println("readPkg err =", err)
return
}
}
var LoginMes message.LoginMes
json.Unmarshal([]byte(mes.Data), &LoginMes)
var LoginResMes message.LoginResMes
if LoginMes.UserId == 100 && LoginMes.UserPwd == "root" {
LoginResMes.Code = "200"
LoginResMes.Error="登录成功"
} else {
LoginResMes.Code = "500"
LoginResMes.Error="登录失败"
}
//准备好数据发送给客户端
var resMsg message.Message
resMsg.Type = message.LoginResMesType
data, err := json.Marshal(LoginResMes)
if err != nil {
fmt.Println("json.Marshal(LoginResMes) err=", err)
}
resMsg.Data = string(data)
data, err = json.Marshal(resMsg)
if err != nil {
fmt.Println("json.Marshal(resMsg) err=", err)
}
//发送长度
err = Write(conn, data)
return
}
}
func main() {
listen, err := net.Listen("tcp", "127.0.0.1:8899")
if err != nil {
fmt.Println("listen err=", err)
}
defer listen.Close()
for {
conn, err := listen.Accept()
if err != nil {
fmt.Println("Accept err=", err)
}
go process(conn)
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接