go开发聊天室(基于tcp协议)

此项目参照韩顺平老师教程,特此感谢。

项目结构如下:

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, _ := re

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值