代码拉取完成,页面将自动刷新
package gim_broker
import (
"fmt"
"gim-broker/utils"
"google.golang.org/protobuf/proto"
"log"
"net"
"strings"
)
type TcpServer struct {
Port int32
}
func (s *TcpServer) Bind() (err error) {
address := fmt.Sprintf("%s%s%d", "0.0.0.0", ":", s.Port)
addr, _ := net.ResolveTCPAddr("tcp", address)
listener, err := net.ListenTCP("tcp", addr)
if err != nil {
fmt.Println(err)
return err
}
Logger.Error("gim-broker启动成功")
go removeInvalidClient()
for {
conn, err := listener.AcceptTCP()
if err != nil {
fmt.Println(err)
continue
}
c := NewHeartBeatInfo(conn) // 客户端对应的心跳数据结构
go HandlerConn(conn, c) // 处理客户端数据交互
go heartBeatDetection(conn, c) // 处理客户端心跳
}
}
func getIp(conn *net.TCPConn) string {
return strings.Split(conn.RemoteAddr().String(), ":")[0]
}
func HandlerConn(conn *net.TCPConn, c *heartBeatInfo) {
Logger.Infof("客户端[连接] ip %s", getIp(conn))
for {
command, data, err := decode(conn)
if err != nil {
log.Println("Failed to read message:", err)
// 释放资源
releaseByConn(conn)
return
}
Logger.Info("###################")
Logger.Info(command)
Logger.Info(utils.HexDump(data))
Logger.Info("******************")
c.heartbeat <- data // 更新收到的最后一条信息用于判断多久没有收到客户端数据
switch command {
case CommandHeartbeat:
//heartbeat(conn, data)
// todo 心跳信息中暂时没有加入额外信息,如版本,身份信息等,可以展示不处理
break
case CommandJoin:
join(conn, data)
break
case CommandQuit:
quit(data)
break
case CommandTransfer:
err := Transfer(data)
if err != nil {
Logger.Error(err)
}
break
case CommandJoinGroup:
joinGroup(data)
}
}
}
/*
*
心跳数据
*/
func heartbeat(conn *net.TCPConn, data []byte) {
msg := &HeartbeatMsg{}
err := proto.Unmarshal(data, msg)
if err != nil {
Logger.Error(err)
return
}
}
/*
客户端加入
conn 连接信息
data 消息数据
*/
func join(conn *net.TCPConn, data []byte) {
msg := &JoinMsg{}
err := proto.Unmarshal(data, msg)
if err != nil {
Logger.Error(err)
return
}
ip := getIp(conn)
client := &Client{ClientId: msg.ClientId, Ip: ip, Conn: conn}
_ = PutClient(client)
}
/*
*
客户端退出,释放相关资源
*/
func quit(data []byte) {
msg := &QuitMsg{}
err := proto.Unmarshal(data, msg)
if err != nil {
Logger.Error(err)
return
}
release(msg)
}
/*
*
释放资源
*/
func release(msg *QuitMsg) {
cli := GetClientById(msg.ClientId)
releaseByConn(cli.Conn)
}
func releaseByConn(conn *net.TCPConn) {
client := GetClientByConn(conn)
if client != nil {
DeleteClientById(client.ClientId)
}
DeleteClientByConn(conn)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。