Giter Club home page Giter Club logo

go-chat's Introduction

go-chat

A chat server is written by golang.

部署与运行

  1. 编译原代码:

go build main.go

  1. 将config目录及web目录复制到执行文件所在目录中。之后便可以直接执行文件

./main

  1. 若需要后台守护执行,在Linux下,可以使用如下指令:

nohup ./main > /dev/null &

  1. 在浏览器中输入

http://127.0.0.1:12345

打开页面进行访问,需要模拟多个用户时,则多次打开即可。若IP不为127.0.0.1,则需要修改web/index.html中的相应IP。若需要修改端口,则需要同时修改web/index.html及main.go中的端口信息。

在WEB上,首先需要输入一个用户名并进行登录,登录成功后,这时可以见到房间列表,可以选择一个房间进入。如果房间列表为空,可以自行创建一个房间,创建后会自动进入该房间。

进入房间后,会自动下发近50条当前房间和消息。这时可以输入消息或GM指令在文本框中并点击“发送”。则可以发送消息或执行相应的GM操作。

目录说明

api 该目录下存放相关的api处理逻辑,每个api方法对应一条请求指令,api按类型分组,每组一个文件

config 该目录用于存放一些配置文件,当前只有filter.txt这一个过滤词库

model 该目录主要存放数据结构

router 该目录用于处理指令与api的关系

service 该目录存放核心业务逻辑类

utils 该目录存放一些工具类

web 该目录下存放的是客户端

逻辑说明

首先,系统中各个模块的大概的调用行为一般为:main -> router -> api -> service -> model

系统本身比较简单,采用websocket进行通讯。当客户端连接上服务端后,在accept方法中,会先接收用户名,接收到用户名后则会使用连接与用户名创建UserInfo对象。并将其添加到用户列表中,这样以后便可以根据用户名获取到用户对象了。

每个用户会有一个发送消息的协程、一个接收消息的协程以及一个逻辑协程。当用户相关数据创建完毕后,程序则会进入这三个协程的消息循环。直到出现定时消息(如心跳)、用户请求消息、数据下发消息,才会进行相应的处理。

接收协程每次只会接收一条消息,将其放入接收队列后便会被挂起,在这条消息被消费前不会再接收其它新的消息。而发送消息是异步执行发送任务的,在缓冲区未满的情况下是不需要等待发送完成的。接收到的消息会放入model.Conn的Received接收队列中,而需要发送的消息则会放入Sending发送队列中。

Received队列中的消息是靠Router.DoCmd中的消息循环来消费。Rounter.DoCmd会依据不同的cmd将逻辑分发给不同的API处理,API处理时,会调用相关的service。

协议说明

在websocket的基础上,我们采用了json协议(除了一开始的获取用户名是字符串外,其它均是json)。而基本的消息结构为: { cmd: xxx, body: xxx } 其中body是可以为任意类型的,根据不同的指令而有不同的数据结构。比如,我们下发消息的JSON则为: { cmd:"msg", body: { from:"xxx", room_id: 1, msg: "hello,world!" } }

请求创建房间

请求指令 { cmd: "newroom", body: null }

创建房间成功后,则会直接下发进入房间的指令及房间的历史消息推送。

请求进入房间

请求指令 { cmd: "setroom", body: 房间ID }

进入房间后,系统会自动下发该房间的历史消息

通知进入房间

通知指令 { cmd: "enterroom", body: 房间ID }

请求离开房间

请求指令 { cmd: "leaveroom", body: null }

由于一个用户同一时间只能进入一个房间,所以这里是不需要携带房间ID的,当前所在房间ID会记录在UserInfo中。

通知离开房间

通知指令 { cmd: "leaveroom", body: null }

请求房间列表

请求指令 { cmd: "roomlist" body: null }

请求返回当前所有房间的列表

通知房间列表

通知指令 { cmd: "roomlist", body: { list: [房间ID1,房间ID2,...] } }

返回房间列表,这里只有房间ID

请求房间历史消息

请求指令 { cmd: "history", body: 房间ID }

请求获取最近的50条房间消息

心跳请求

请求指令 { cmd: "heartjump", body: null, }

一般会由系统每15秒下发一个心跳通知,这时客户端必须回复此指令,不然系统在尝试2次后将会关闭当前用户的连接

心跳通知

通知指令 { cmd: "heartjump", body: null, }

每15秒下发给客户端,必须及时回复

请求发送消息

请求指令 { cmd: "sendmsg", body: "消息内容" }

请求在当前所在的房间里向房间里的所有人发送一条消息,这条消息会被Filter所过滤后转发给当前房间的所有人。被过滤的内容会被替换为*

消息通知

通知指令 { cmd: "msg", body: { from: "发送者名称", room_id: 房间ID, msg: "消息内容", } }

此指令会用于下发消息使用,包括实时发送的消息及房间的历史消息。

系统消息通知

通知指令 { cmd: "msg", body: { from: "SYSTEM", room_id: 0, msg: "消息内容", } }

此指令用于发送系统消息,当前主要是用于回复GM指令的结果使用。

关于过滤处理逻辑

  1. 词库存储格式

为了提高过滤的处理速度,词库需要以特定的格式在内存中进行存储。当前使用的多层Hash的结构。顶层Hash的KEY为词的第一字,第二层为第二字,依次类推直到存储完毕。

若现在需要存储 hello及 world这两个词,若用伪代码表示,则它们将会被存储如下:

map[h][e][l][l][o] 及 map[w][o][r][l][d]

最大层数与词库中最长单词的长度一致。

  1. 过滤处理

在过滤时,会遍历消息字符串,依次去匹配多层Hash的KEY,若匹配上,则过滤当前单词。在匹配时会尽量匹配最长可匹配单词。即是说,若我们有过滤词:abc 及 abcd,针对消息abcdef过滤时,结果为****ef

  1. 中文支持

词库使用rune进行存储,支持中文及其它文字的过滤

关于拓展

由于时间原因,当前架构为单机架构,若需要更多的IO处理,可以进行分服处理(需要调整代码),采用微服务架构。主要**为,将用户管理、房间管理、过滤服务进行分离。每个房间(所在哪个服务器)均需要在房间管理服务中注册,进入房间前由房间管理服务返回IP地址。若不使用网关,则可以直接将房间服务器IP及端口返回给客户端,由客户端直连。用户管理主要管理当前用户的信息,以防止重复登录的情况发生。同时记录当前用户所在的房间服务器及房间号。采用这类架构后,吞吐量可以提高,延迟会有所增加。

go-chat's People

Contributors

joy999 avatar

Watchers

 avatar  avatar

Forkers

lindows365

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.