此项目参照韩顺平老师教程,特此感谢。
项目结构如下:
client,server分别是客户端和服务端代码包,common为公共文件函数包;
main,model,processf分别存放主程序文件,结构体文件和方法文件,其中server下model中的Dao.go是redis连接池配置文件,引用了redis的git代码包地址:https://github.com/gomodule/redigo,下载后按说明引用。
运行项目:
1.开启服务端
2.开启客户端(一个或多个)
3.注册并登录后显示
4.再登陆几个客户端,就可以互相发送消息和传送文件以及其他用户上下线服务端消息提醒了
代码如下:
server端:
main/main.go:
package main
import (
"learn/chatroom/server/mainProcess"
"learn/chatroom/server/model"
"time"
)
func main() {
//初始化连接池得到全局连接池变量pool
model.PoolInit(8, 0, time.Second * 100, "tcp", "localhost:6379")
//启动服务端进程
mainProcess.GetMainProcess().OnlyProcess()
}
mainProcess/mainProcess.go:
package mainProcess
import (
"fmt"
"net"
"learn/chatroom/common/utils"
"learn/chatroom/common/message"
"learn/chatroom/server/process"
)
type MainProcess struct {
Conn net.Conn
}
func GetMainProcess() *MainProcess {
return &MainProcess{}
}
func (this *MainProcess) OnlyProcess() {
fmt.Println("server开始监听。。。")
listen, err := net.Listen("tcp", "0.0.0.0:9999")
if err != nil {
fmt.Println("listen err=", err)
return
}
defer listen.Close()
for {
fmt.Println("等待客户端连接。。。")
//等待并返回下一个连接到该接口的连接
conn, err_accp := listen.Accept()
this.Conn = conn
if err_accp != nil {
fmt.Println("err_accp=", err_accp)
} else {
fmt.Printf("客户端network=%v,ip=%v连接成功\n", conn.RemoteAddr().Network(), conn.RemoteAddr().String())
//协程处理多个连接
go this.process(conn)
}
}
}
//登录后处理其他业务
func (this *MainProcess) process(conn net.Conn) {
user := process.GetUserProcess(conn)
defer conn.Close()
defer func (){//匿名函数处理用户下线业务
var uid int
loggedUser := process.GetLoggedUser()
//获取当前用户id
for i, mp := range *loggedUser {
for id, co := range mp {
if co == conn {
uid = id
//去掉当前下线用户
*loggedUser = append((*loggedUser)[:i], (*loggedUser)[i + 1:]...)
}
}
}
//fmt.Println("unline uid=", uid)
//说明未获取当前用户id
if uid == 0 {
return
}
//通知其他线上用户
for _, mp := range *loggedUser {
for _, co := range mp {
if co == conn {
continue
}
user.NotifyOtherUsers(uid, co, 0)
}
}
}()
var mes, mes_back message.Message
var resmes message.ResMes
for {
err := utils.ReceiveMsg(conn, &mes)
if err != nil {
fmt.Println("服务器接受信息失败")
return
}
switch mes.Type {
case 1 ://登录类型请求
user.DoLogin(mes, mes_back, resmes)
case 2 ://注册类型请求
user.DoRegister(mes, mes_back, resmes)
case 3 ://显示在线用户
user.ShowUserOnline(mes_back)
case 4 ://用户发送消息
user.SendMes(mes, mes_back)
case 6 ://查看消息
user.SearchMesList(mes, mes_back)
case 7 ://发送文件
user.SendFile(mes, mes_back)
}
}
}
model/Dao.go:
package model
import (
"github.com/garyburd/redigo/redis"
"time"
)
var pool *redis.Pool
func PoolInit(maxIdle int, maxActive int, idleTimeout time.Duration, network string, address string) {
//初始化连接池
pool = &redis.Pool{
MaxIdle : maxIdle,
MaxActive : maxActive,
IdleTimeout : idleTimeout,
Dial : func() (redis.Conn, error){
return redis.Dial(network, address)
},
}
}
model/user.go:
package model
type User struct {
UserId int `json:"id"`
UserName string `json:"name"`
UserPwd string `json:"pwd"`
}
model/userDao.go:
package model
import (
"github.com/garyburd/redigo/redis"
"fmt"
"encoding/json"
"learn/chatroom/common/message"
"time"
)
type UserDao struct {
Con redis.Conn
}
func NewUserDao() *UserDao {
return &UserDao{pool.Get()}
}
//根据id获取user
func (this *UserDao) GetUserById(id int, user *User) error {
user2, err := redis.String(this.Con.Do("hget", "users", id))
if err != nil {
fmt.Println("redis.String err=", err)
return err
}
err = json.Unmarshal([]byte(user2), user)
if err != nil {
fmt.Println("json.Unmarshal err=", err)
return err
}
return nil
}
//新增user
func (this *UserDao) AddUser(mes message.LoginMes) error {
//先检查用户id是否重复
user_old, _ := redis.String(this.Con.Do("hget", "users", mes.UserId))
fmt.Println("user_old=", user_old)
if user_old != "" {
fmt.Println("用户已存在!!!")
return fmt.Errorf("用户已存在!!!")
}
user := User{UserId : mes.UserId, UserName : mes.UserName, UserPwd : mes.UserPwd}
userJson, err := json.Marshal(user)
if err != nil {
fmt.Println("userJson, err=", err)
return err
}
_, err = this.Con.Do("hset", "users", mes.UserId, string(userJson))
if err != nil {
fmt.Println("hset user err=", err)
return err
}
return nil
}
//保存消息
func (this *UserDao) SaveMes(uid int, toUid int, content string) error {
str := fmt.Sprintf("%dto%d", uid, toUid)
_, err := this.Con.Do("hset", str, time.Now().UnixNano(), content)
if err != nil {
fmt.Println("SaveMes hset err=", err)
return err
}
return nil
}
//用户查看消息记录,由于redis包识别不了hgetall指令,姑只取一条作示例
func (this *UserDao) SearchMesList(idToId string) string {
data, err := redis.String(this.Con.Do("hget", idToId, "1576641743776366500"))
if err != nil {
fmt.Println("hgetall idToId err=", err)
return ""
}
return data
}
process/userManage.go:
package process
//已上线用户管理
import (
"net"
)
type AllLoggedUser struct {
LoggedUser []map[int]net.Conn
}
var (
allLoggedUser AllLoggedUser
)
func GetLoggedUser() *[]map[int]net.Conn {
return &allLoggedUser.LoggedUser
}
//已上线变量添加用户
func (this *AllLoggedUser) AddUser(id int, conn net.Conn) {
mp := make(map[int]net.Conn)
mp[id] = conn
this.LoggedUser = append(this.LoggedUser, mp)
}
//已上线变量删除下线用户
func (this *AllLoggedUser) DelUser(id int) {
for i, val := range this.LoggedUser {
for uid, _ := range val {
if uid == id {
this.LoggedUser = append(this.LoggedUser[:i], this.LoggedUser[i + 1 :]...)
}
}
}
}
process/userProcess.go:
package process
import (
"learn/chatroom/common/message"
"learn/chatroom/common/utils"
"learn/chatroom/server/model"
"encoding/json"
"net"
"fmt"
)
type UserProcess struct {
Conn net.Conn
}
func GetUserProcess(conn net.Conn) *UserProcess {
return &UserProcess{conn}
}
//登录
func (this *UserProcess) DoLogin(mes message.Message, mes_back message.Message, resmes message.ResMes) {
var data_login message.LoginMes
var user model.User
mes_back.Type = -1
json.Unmarshal([]byte(mes.Data), &data_login)
err := model.NewUserDao().GetUserById(data_login.UserId, &user)
if err !=nil {
resmes.Code = 300
resmes.Msg = "未注册!!!"
} else if data_login.UserPwd == user.UserPwd {
resmes.Code = 200
resmes.Msg = "服务端验证成功!!!"
//通知其他线上用户
for _, mp := range allLoggedUser.LoggedUser {
for id, conn := range mp {
if id == user.UserId {
continue //跳过自己
}
this.NotifyOtherUsers(data_login.UserId, conn, 1)
}
}
//新增已登录用户到变量LoggedUser
allLoggedUser.AddUser(user.UserId, this.Conn)
} else {
resmes.Code = 300
resmes.Msg = "服务端验证失败!!!"
}
mesres_json, err := json.Marshal(resmes)
mes_back.Data = string(mesres_json)
err = utils.SendMsg(this.Conn, mes_back)
if err != nil {
fmt.Println("服务器反馈信息失败")
}
}
//注册
func (this *UserProcess) DoRegister(mes message.Message, mes_back message.Message, resmes message.ResMes) {
var data_login message.LoginMes
mes_back.Type = -2
json.Unmarshal([]byte(mes.Data), &data_login)
err := model.NewUserDao().AddUser(data_login)
if err !=nil {
resmes.Code = 300
resmes.Msg = "服务端新增用户失败!!!"
} else {
resmes.Code = 200
resmes.Msg = "服务端新增用户成功!!!"
}
mesres_json, err := json.Marshal(resmes)
mes_back.Data = string(mesres_json)
err = utils.SendMsg(this.Conn, mes_back)
if err != nil {
fmt.Println("服务器反馈新增信息失败")
}
}
//显示在线用户
func (this *UserProcess) ShowUserOnline(mes_back message.Message) {
mes_back.Type = -3
users := make([]model.User, 10)
for _, mp := range allLoggedUser.LoggedUser {
for id, _ := range mp {
var user model.User
model.NewUserDao().GetUserById(id, &user)
users[id] = user
}
}
loggedUserJson, err := json.Marshal(users)
mes_back.Data = string(loggedUserJson)
err = utils.SendMsg(this.Conn, mes_back)
if err != nil {
fmt.Println("服务器反馈在线用户信息失败")
}
}
//用户向其他用户发送消息
func (this *UserProcess) SendMes(mes message.Message, mes_back message.Message) {
var sendmes message.SendMes
mes_back.Type = -4
err := json.Unmarshal([]byte(mes.Data), &sendmes)
if err != nil {
fmt.Println("服务端反序列化sendmes失败!!!")
return
}
last_content := fmt.Sprintf("%d said to %d:%s\n",sendmes.Uid, sendmes.ToUid, sendmes.Content)
mes_back.Data = last_content
//保存消息到redis
err = model.NewUserDao().SaveMes(sendmes.Uid, sendmes.ToUid, last_content)
if err != nil {
return
}
//用以判断目标客户是否在线
isOnline := false
//发送消息到对应的用户
for _, mp := range allLoggedUser.LoggedUser {
for id, conn := range mp {
if id == sendmes.ToUid {
isOnline = true
err = utils.SendMsg(conn, mes_back)
}
}
}
if isOnline == false {//离线时,起一个携程监听客户上线再发送
go this.WatchUserIsOnline(sendmes.ToUid, mes_back)
}
}
//离线发送消息
func (this *UserProcess) WatchUserIsOnline(toUid int, mes_back message.Message) {
boo := true
for boo{
for _, mp := range allLoggedUser.LoggedUser {
for id, conn := range mp {
if id == toUid {
err := utils.SendMsg(conn, mes_back)
if err != nil {
fmt.Println("服务端离线发送消息失败!!!")
}
boo = false
}
}
}
}
}
//通知其他用户上线 onlineOrUnline=1->上线,否则下线
func (this *UserProcess) NotifyOtherUsers(currentId int, conn net.Conn, onlineOrUnline int) {
var mes message.Message
var str string
mes.Type = -5
if onlineOrUnline == 1 {
str = fmt.Sprintf("id为%d的用户已上线", currentId)
} else {
str = fmt.Sprintf("id为%d的用户已下线", currentId)
}
mes.Data = str
err := utils.SendMsg(conn, mes)
if err != nil {
fmt.Println("服务端推送消息失败")
}
}
//用户查看消息记录
func (this *UserProcess) SearchMesList(mes message.Message, mes_back message.Message) {
content := model.NewUserDao().SearchMesList(mes.Data)
mes_back.Type = -6
mes_back.Data = content
err := utils.SendMsg(this.Conn, mes_back)
if err != nil {
fmt.Println("服务端查询消息列表失败")
}
}
//发送文件
func (this *UserProcess) SendFile(mes message.Message, mes_back message.Message) {
var fileMes message.FileMes
json.Unmarshal([]byte(mes.Data), &fileMes)
mes_back.Type = -7
mes_back.Data = mes.Data
for _, mp := range allLoggedUser.LoggedUser {
for id, conn := range mp {
if id == fileMes.ToUid {
err := utils.SendMsg(conn, mes_back)
if err != nil {
fmt.Println("服务端发送文件失败!!!")
}
}
}
}
}
---------------------------------------------------------------------------分界线------------------------------------------------------------------------------------
client:
main/main.go:
package main
import (
"fmt"
"learn/chatroom/client/process"
"net"
"os"
)
func main() {
var key int
var loop = true
var uid int
var name string
var pwd string
conn := GetConn()
for {
mainMenu(&loop, &key)
switch key {
case 1 :
toLogin(&uid, &pwd, conn)
//登录后显示菜单
process.ShowMenu(conn, uid)
case 2 :
toRegister(&uid, &name, &pwd, conn)
case 3 :
os.Exit(0)
}
}
}
func GetConn() net.Conn {
//建立连接
conn, err_conn := net.Dial("tcp", "192.168.2.149:9999")
if err_conn != nil {
fmt.Println("conn err =", err_conn)
}
return conn
}
func toLogin(uid *int, pwd *string, conn net.Conn){
for {
fmt.Println("请输入用户id")
fmt.Scanln(uid)
fmt.Println("请输入用户密码")
fmt.Scanln(pwd)
userProcess := process.GetUserProcess(conn)
err_login := userProcess.DoLogin(uid, pwd)
if err_login != nil {
fmt.Println("用户名或密码错误,请重新输入")
} else {
break
}
}
}
func toRegister(uid *int, name *string, pwd *string, conn net.Conn) {
for {
fmt.Println("请输入用户id")
fmt.Scanln(uid)
fmt.Println("请输入用户暱称")
fmt.Scanln(name)
fmt.Println("请输入用户密码")
fmt.Scanln(pwd)
userProcess := process.GetUserProcess(conn)
err := userProcess.DoRegister(uid, name, pwd)
if err != nil {
fmt.Println("注册失败,请重新输入")
} else {
break
}
}
}
func mainMenu(loop *bool, key *int) {
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.Scanln(key)
switch *key {
case 1 :
fmt.Println(" 登录聊天室 ")
*loop = false
case 2 :
fmt.Println(" 注册用户 ")
*loop = false
case 3 :
fmt.Println(" 退出系统 ")
*loop = false
default :
fmt.Println(" 输入错误,请重新输入 ")
}
}
}
model/user.go:
package model
type User struct {
UserId int `json:"id"`
UserName string `json:"name"`
UserPwd string `json:"pwd"`
}
process/server.go:
package process
import (
"fmt"
"os"
"net"
"learn/chatroom/common/utils"
"learn/chatroom/common/message"
"learn/chatroom/client/model"
"encoding/json"
"io/ioutil"
)
//登录后菜单
func ShowMenu(conn net.Conn, uid int) {
fmt.Println("-------------------恭喜xxx登陆成功----------------------")
var num int
up := GetUserProcess(conn)
for {
fmt.Println(" 1.显示在线用户 ")
fmt.Println(" 2.发送消息")
fmt.Println(" 3.信息列表")
fmt.Println(" 4.发送文件")
fmt.Println(" 5.退出系统")
fmt.Println("请选择1-4")
fmt.Scanln(&num)
switch num {
case 1 :
up.ShowUserOnline()
case 2 :
up.SendMes(uid)
case 3 :
up.SearchMesList(uid)
case 4 :
up.SendFile(uid)
case 5 :
fmt.Println("退出系统")
os.Exit(0)
default :
fmt.Println("输入错误,请重新输入")
}
}
}
//监听服务端推送消息
func ServerProcessMes(conn net.Conn) {
//fmt.Println("ServerProcessMes 等待服务器消息")
for {
var mes message.Message
err := utils.ReceiveMsg(conn, &mes)
if err != nil {
fmt.Println("ServerProcessMes utils.ReceiveMsg fail")
return
}
//fmt.Println("ServerProcessMes 获取的mes=", mes)
switch mes.Type {
case -3 :
users := make([]model.User, 10)
json.Unmarshal([]byte(mes.Data), &users)
fmt.Println("在线用户如下:")
for _, user := range users {
if user.UserId > 0 {
fmt.Printf("用户id=%d\tname=%s\tpwd=%s\n", user.UserId, user.UserName, user.UserPwd)
}
}
case -4, -5, -6:
fmt.Println(mes.Data)
case -7 :
ReceiveFile(mes)
default :
fmt.Println("ServerProcessMes mes", mes)
}
}
}
//接受文件
func ReceiveFile(mes message.Message) {
var fileMes message.FileMes
json.Unmarshal([]byte(mes.Data), &fileMes)
var path string
path = fmt.Sprintf("d:/ctfiles/%s", fileMes.FileName)
err := ioutil.WriteFile(path, fileMes.Content, 0666)
if err != nil {
fmt.Println("write err=", err)
} else {
str := fmt.Sprintf("接收用户id=%d的文件%s成功!!!", fileMes.Uid, fileMes.FileName)
fmt.Println(str)
}
}
process/userProcess.go:
package process
//客户端用户业务
import (
"fmt"
"learn/chatroom/common/message"
"learn/chatroom/common/utils"
"net"
"encoding/json"
"io/ioutil"
"strings"
)
type UserProcess struct {
Conn net.Conn
}
//实例化
func GetUserProcess(conn net.Conn) *UserProcess {
return &UserProcess{Conn : conn}
}
//登录请求
func (this *UserProcess) DoLogin(uid *int, pwd *string ) error {
//mes为发送到服务端信息,mes_back为服务端反馈信息
var mes, mes_back message.Message
logmes := message.LoginMes{UserId : *uid, UserPwd : *pwd}
mes.Type = 1
loginJson, err := json.Marshal(logmes)
if err != nil {
fmt.Println("logindata marshal err=", err)
return err
}
mes.Data = string(loginJson)
err_send := utils.SendMsg(this.Conn, mes)
if err_send != nil {
return err_send
}
err_receive := utils.ReceiveMsg(this.Conn, &mes_back)
if err_receive != nil {
fmt.Println("客户端接收反馈信息失败")
return err_receive
}
//resmes为服务端反馈的具体信息
var resmes message.ResMes
json.Unmarshal([]byte(mes_back.Data), &resmes)
//反馈登陆成功
if mes_back.Type == -1 && resmes.Code == 200 {
fmt.Println(resmes)
//监听服务端的消息,如好友上线,发来消息等
go ServerProcessMes(this.Conn)
return nil
}
return fmt.Errorf("客户端接收反馈信息错误")
}
//注册请求
func (this *UserProcess) DoRegister(uid *int, name *string, pwd *string) (err error) {
//mes为发送到服务端信息,mes_back为服务端反馈信息
var mes, mes_back message.Message
logmes := message.LoginMes{UserId : *uid, UserName : *name, UserPwd : *pwd}
mes.Type = 2
registerJson, err := json.Marshal(logmes)
if err != nil {
fmt.Println("register-data marshal err=", err)
return
}
mes.Data = string(registerJson)
err = utils.SendMsg(this.Conn, mes)
if err != nil {
return
}
err = utils.ReceiveMsg(this.Conn, &mes_back)
if err != nil {
fmt.Println("客户端接收反馈信息失败")
return
}
//resmes为服务端反馈的具体信息
var resmes message.ResMes
json.Unmarshal([]byte(mes_back.Data), &resmes)
//反馈注册成功
if mes_back.Type == -2 && resmes.Code == 200 {
fmt.Println(resmes.Msg)
err = nil
return
}
err = fmt.Errorf("客户端接收反馈信息错误")
return
}
//显示在线用户
func (this *UserProcess) ShowUserOnline() {
var mes message.Message
mes.Type = 3
err := utils.SendMsg(this.Conn, mes)
if err != nil {
fmt.Println("客户端发送反馈信息失败")
return
}
}
//用户发送消息
func (this *UserProcess) SendMes(uid int) {
var toUid int
var content string
fmt.Println("请输入想聊天对象的id:")
fmt.Scanln(&toUid)
fmt.Println("请输入聊天内容:")
fmt.Scanln(&content)
fmt.Printf("%d said to %d: %s\n", uid, toUid, content)
var mes message.Message
mes.Type = 4
var dataSend message.SendMes
dataSend.Uid = uid
dataSend.ToUid = toUid
dataSend.Content = content
dataJson, err := json.Marshal(dataSend)
mes.Data= string(dataJson)
if err != nil {
fmt.Println("json.Marshal(data)失败")
return
}
err = utils.SendMsg(this.Conn, mes)
if err != nil {
fmt.Println("客户端发送信息失败")
return
}
}
//查看消息列表
func (this *UserProcess) SearchMesList(uid int) {
var toid int
var mes message.Message
fmt.Println("请输入目标用户的id")
fmt.Scanln(&toid)
content := fmt.Sprintf("%dto%d", uid, toid)
mes.Type = 6
mes.Data = content
err := utils.SendMsg(this.Conn, mes)
if err != nil {
fmt.Println("查看消息列表失败")
}
}
//发送文件
func (this *UserProcess) SendFile(uid int) {
var filePath string
var toUid int
var fileName string
var mes message.Message
var fileMes message.FileMes
fmt.Println("请输入文件地址:")
fmt.Scanln(&filePath)
fmt.Println("请输入接收对象id:")
fmt.Scanln(&toUid)
//判断文件是否存在
ok, _ := utils.PathExists(filePath)
if !ok {
fmt.Println("文件夹不存在!!!")
return
}
//获取文件名和内容
strs := strings.Split(filePath, "/")
fileName = strs[len(strs) - 1]
content, err_cont := ioutil.ReadFile(filePath)
if err_cont != nil {
fmt.Println("读取文件内容失败!!!")
return
}
//封装消息体
fileMes.Uid = uid
fileMes.ToUid = toUid
fileMes.FileName = fileName
fileMes.Content = content
fileJson, _ := json.Marshal(fileMes)
mes.Type = 7
mes.Data = string(fileJson)
err := utils.SendMsg(this.Conn, mes)
if err != nil {
fmt.Println("发送文件失败!!!")
}
fmt.Println("发送文件成功!!!")
}
--------------------------------------------------------------------------------------分界线-------------------------------------------------------------------------
common:
message/message.go:
package message
type Message struct {
//类型 1-登录-1-登陆反馈 2-注册 -2 -注册反馈 3-显示在线用户 -3,-显示在线用户反馈 4-用户向用户发送信息 -4,反馈 -5,-服务器推送消息
//6-用户查看消息列表 -6,反馈 7-用户发送文件 -7,反馈
Type int
Data string //数据
}
type LoginMes struct {
UserId int `json:"id"`
UserPwd string `json:"pwd"`
UserName string `json:"name"`
}
type ResMes struct {
Code int //返回状态码 100-未注册 200-成功 300-失败
Msg string //信息
}
type SendMes struct {
Uid int `json:"uid"`
ToUid int `json:"touid"`
Content string `json:"content"`
}
type FileMes struct {
Uid int
ToUid int
FileName string
Content []byte
}
utils/cli_to_ser.go:
package utils
//客户端和服务端相互推送消息
import (
"net"
"learn/chatroom/common/message"
"encoding/json"
"encoding/binary"
"fmt"
"os"
)
func SendMsg(conn net.Conn, mes message.Message) error {
mesJson, err_mesJson := json.Marshal(mes)
if err_mesJson != nil {
fmt.Println("mes marshal err=", err_mesJson)
return err_mesJson
}
//定义传输字节长度
meslen := uint32(len(mesJson))
buf := make([]byte, 4)
//uint32转成[]byte,以便conn.Write()
binary.BigEndian.PutUint32(buf[:4], meslen)
//发送数据长度
n, err_write := conn.Write(buf[:4])
if err_write !=nil || n != 4 {
fmt.Println("mes-length write err=", err_write)
return err_write
}
//fmt.Printf("发送了%v个字节\n", len(mesJson))
//fmt.Println("发送的data=", string(mesJson))
//发送登录数据
_, err_write = conn.Write(mesJson)
if err_write !=nil {
fmt.Println("mes-data write err=", err_write)
return err_write
}
return nil
}
func ReceiveMsg(conn net.Conn, mes *message.Message) (error){
//定义接收字节变量
buf := make([]byte, 8192)
//conn.Read()等待客户端发送消息,如果没有write[发送],那么协程阻塞在这里
//读取前四个字节,数据长度
n, err := conn.Read(buf[:4])
if err != nil || n != 4 {
fmt.Println("server read len err=", err)
fmt.Println("客户端退出。。。")
return err
}
//获取接受的数据长度。将[]byte转成uint32
data_len := binary.BigEndian.Uint32(buf[:4])
//接收已知长度的数据
n, err = conn.Read(buf[:data_len])
if n != int(data_len) || err !=nil {
fmt.Println("server read data err=", err)
fmt.Println("客户端退出。。。")
return err
}
//fmt.Println("接收到的data_len=", data_len)
//fmt.Println("接收到的data=", string(buf[:data_len]))
json.Unmarshal(buf[:data_len], mes)
return nil
}
//判断文件文件是否存在
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
以上就是全部