博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
go语言多房间聊天室websocket(二)
阅读量:4167 次
发布时间:2019-05-26

本文共 7065 字,大约阅读时间需要 23 分钟。

这一篇将继续实现go语言的多房间聊天室,第一篇实现了基本的功能,今天就继续完善,实现各种功能。

广播功能:就是游戏里的全服通告,
信息过滤:对言论信息处理,类似于不能发黄赌毒信息,
禁言功能:此处警告并禁言5分钟;
踢出群聊功能:三次不合法信息后,提醒以后并踢出群聊;

功能代码:

由于内容较多,分成两个文件来写了;

hub.go文件:

package mainimport (	"github.com/gorilla/websocket"	"log"	"net/http"	"strings"	"time")const (	writeWait = 10 * time.Second	pongWait = 60 * time.Second	pingPeriod = (pongWait * 9) / 10	maxMessageSize = 512)var( upgrader = websocket.Upgrader{
ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool {
return true },})type connection struct {
ws *websocket.Conn send chan []byte numberv int forbiddenword bool timelog int64}func (m message) readPump() {
c := m.conn defer func() {
h.unregister <- m c.ws.Close() }() c.ws.SetReadLimit(maxMessageSize) c.ws.SetReadDeadline(time.Now().Add(pongWait)) c.ws.SetPongHandler(func(string) error {
c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil }) for {
_, msg, err := c.ws.ReadMessage() if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Printf("error: %v", err) } //log.Printf("error: %v", err) break } go m.Kickout(msg) }}// 信息处理,不合法言论 禁言警告,超过3次,踢出群聊;func (m message) Kickout(msg []byte) {
c := m.conn // 判断是否有禁言时间,并超过5分钟禁言时间,没有超过进入禁言提醒 nowT:=int64(time.Now().Unix()) if nowT-c.timelog<300{
h.warnmsg <- m } // 不合法信息3次,判断是否有不合法信息,没有进行信息发布 if c.numberv < 3 {
// 信息过滤,设置含有此字符串内字符为不合法信息, basestr := "死亡崩薨" teststr := string(msg[:]) for _, ev := range teststr {
// 判断字符串中是否含有某个字符,true/false reslut := strings.Contains(basestr, string(ev)) if reslut == true {
c.numberv += 1 c.forbiddenword = true // 禁言为真 // 记录禁言开始时间,禁言时间内任何信息不能发送 c.timelog = int64(time.Now().Unix()) h.warnings <- m break } } // 不禁言,消息合法 可以发送 if c.forbiddenword != true {
// 设置广播消息, 所有房间内都可以收到信息;给广播消息开头加一个特定字符串为标识,当然也有其他方法; // 此例 设置以开头0为标识, 之后去掉0 ; if msg[0] == 48 {
head := string("所有玩家请注意:") data := head + string(msg[1:]) m := message{
[]byte(data), m.roomid, c} h.broadcastss <- m } else if msg[0] != 48 {
//不是0,就是普通消息 m := message{
msg, m.roomid, c} h.broadcast <- m } } // 不合法信息超过三次,踢出群 } else {
h.kickoutroom <- m log.Println("要被踢出群聊了...") c.ws.Close() // 此处关闭了踢出的连接,也可以不关闭做其他操作, }}func (c *connection) write(mt int, payload []byte) error {
c.ws.SetWriteDeadline(time.Now().Add(writeWait)) return c.ws.WriteMessage(mt, payload)}func (s *message) writePump() {
c := s.conn ticker := time.NewTicker(pingPeriod) defer func() {
ticker.Stop() c.ws.Close() }() for {
select {
case message, ok := <-c.send: if !ok {
c.write(websocket.CloseMessage, []byte{
}) return } if err := c.write(websocket.TextMessage, message); err != nil {
return } case <-ticker.C: if err := c.write(websocket.PingMessage, []byte{
}); err != nil {
return } } }}func serverWs(w http.ResponseWriter, r *http.Request) {
r.ParseForm() roomid := r.Form["roomid"][0] ws, err := upgrader.Upgrade(w, r, nil) if err != nil {
log.Println(err) return } c := &connection{
send: make(chan []byte, 256), ws: ws} m := message{
nil, roomid, c} h.register <- m go m.writePump() go m.readPump()}

server.go文件:

package mainimport (	"fmt"	"log"	"net/http")type message struct {
data []byte roomid string conn *connection}type hub struct {
rooms map[string]map[*connection]bool broadcast chan message broadcastss chan message warnings chan message register chan message unregister chan message kickoutroom chan message warnmsg chan message}var h = hub{
broadcast: make(chan message), broadcastss:make(chan message), warnings: make(chan message), warnmsg: make(chan message), register: make(chan message), unregister: make(chan message), kickoutroom: make(chan message), rooms: make(map[string]map[*connection]bool),}func (h *hub) run() {
for {
select {
case m := <-h.register: //传输链接 conns:=h.rooms[m.roomid] if conns == nil {
// 链接保存到相应的房间 conns = make(map[*connection]bool) h.rooms[m.roomid] = conns fmt.Println("在线人数:==",len(conns)) fmt.Println("rooms:==",h.rooms) } h.rooms[m.roomid][m.conn] = true fmt.Println("在线人数:==",len(conns)) fmt.Println("rooms:==",h.rooms) for con := range conns {
delmsg := "系统消息:欢迎新伙伴加入" + m.roomid + "聊天室!!!" data := []byte(delmsg) select {
case con.send <- data: } } case m := <-h.unregister: //断开链接 conns:=h.rooms[m.roomid] if conns != nil {
if _, ok := conns[m.conn]; ok {
delete(conns, m.conn) //删除链接 close(m.conn.send) for con := range conns {
delmsg := "系统消息:有小伙伴离开了" + m.roomid + "聊天室!欢送!!!" data := []byte(delmsg) select {
case con.send <- data: } if len(conns) == 0 {
// 链接都断开,删除房间 delete(h.rooms, m.roomid) } } } } case m := <-h.kickoutroom: //3次不合法信息后,被踢出群聊 conns:=h.rooms[m.roomid] notice:="由于您多次发送不合法信息,已被踢出群聊!!!" select {
case m.conn.send <- []byte(notice): } if conns != nil {
if _, ok := conns[m.conn]; ok {
delete(conns, m.conn) close(m.conn.send) if len(conns) == 0 {
delete(h.rooms, m.roomid) } } } case m := <-h.warnings: //不合法信息警告 conns:=h.rooms[m.roomid] if conns != nil {
if _, ok := conns[m.conn]; ok {
notice := "警告:您发布不合法信息,将禁言5分钟,三次后将被踢出群聊!!!" //starttime:= select {
case m.conn.send <- []byte(notice): } } } case m := <-h.warnmsg: //禁言中提示 conns:=h.rooms[m.roomid] if conns != nil {
if _, ok := conns[m.conn]; ok {
notice := "您还在禁言中,暂时不能发送信息!!!" select {
case m.conn.send <- []byte(notice): } } } case m := <-h.broadcast: //传输群信息/房间信息 conns := h.rooms[m.roomid] for con := range conns {
if con==m.conn{
//自己发送的信息,不用再发给自己 continue } select {
case con.send <- m.data: default: close(con.send) delete(conns, con) if len(conns) == 0 {
delete(h.rooms, m.roomid) } } } case m := <-h.broadcastss: //传输全员广播信息 for _,conns := range h.rooms {
for con:=range conns{
if con==m.conn{
//自己发送的信息,不用再发给自己 continue } select {
case con.send <- m.data: default: close(con.send) delete(conns, con) if len(conns) == 0 {
delete(h.rooms, m.roomid) } } } } } }}// 要运行同包下的几个文件,都要执行//go run server.go hub.gofunc main() {
go h.run() http.HandleFunc("/",serverWs ) err := http.ListenAndServe(":8899", nil) if err != nil {
log.Fatal("ListenAndServe: ", err) }}

结果:

ws://127.0.0.1:8899/?roomid=tang

ws://127.0.0.2:8899/?roomid=tang
ws://127.0.0.3:8899/?roomid=wang
ws://127.0.0.4:8899/?roomid=wang
ws://127.0.0.5:8899/?roomid=wang
记录的打印信息,把请求连接加入多房间聊天室rooms,此处创建了两个房间,
在这里插入图片描述
以下是发送信息的显示结果:
发现有一点没有处理好,就是发的消息有的情况不需要让发信息人看到(显示),
只需要看到提醒信息…有兴趣的小伙伴可以进一步改进,
对于 ***github.com/gorilla/websocket***这个库,我了解使用的还不太多, 只是用它实现了基本功能, 大家也可以深入研究一下,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

转载地址:http://znqxi.baihongyu.com/

你可能感兴趣的文章
http/apache工作原理
查看>>
什么是Web2.0
查看>>
PHP中$_SERVER的详细用法
查看>>
类与对象(PHP5)之三:静态关键字(Static Keyword)
查看>>
SQL里的EXISTS与in、not exists与not in
查看>>
MySQL字符集及MySQL编码转换
查看>>
XSLT简介
查看>>
[翻译]xml的加密和解密
查看>>
Mysql数据库基本操作概要
查看>>
javascript比较日期
查看>>
在脚本中取table单元格的值(javascript)
查看>>
一些有用的js代码
查看>>
性能分析样例
查看>>
C#中out 及 ref 区别
查看>>
数字签名的原理
查看>>
.NET中RAS加解密和签名与验证的c#实现代码讲解,及实现程序提供
查看>>
根据控件ID获取控件
查看>>
ACE篇之四:通过ACE日志策略进行运行时配置
查看>>
ACE篇之五:ACE容器之一(双向链表)
查看>>
ACE篇之六:ACE容器之二(栈)
查看>>