tcp 服务端

1.新建TcpServer 

type TcpServer struct {
       // 记录每个IP的连接数量
       perIPConnCounter ipmanager.PerIPConnCounter
       ln               net.Listener
}
func (tc *TcpServer) Start() {
       var lastPerIPErrorTime time.Time
       //开始接收tcp连接请求
       ln, err := net.Listen("tcp", ":9998")
       if err != nil {
              log.Println("Listen", err.Error())
              return
       }
       tc.ln = ln

       // 接收并处理连接请求
       for {
              c, err := tc.acceptConn(ln, &lastPerIPErrorTime)
              if err != nil {
                     panic("Room" + err.Error())
                     break
              }
              // 启动worker去处理连接
              go tc.serve(c)
       }
}

2.接受tcp请求接口

func (tc *TcpServer) acceptConn(ln net.Listener, lastPerIPErrorTime *time.Time) (net.Conn, error) {
       for {
              c, err := ln.Accept()
              if err != nil {
                     if c != nil {
                            log.Println("[FATAL] net.Listener returned non-nil conn and non-nil error : ", err.Error())
                     }
                     if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
                            log.Println("[ERROR] Temporary error when accepting new connections: ", err.Error())
                            time.Sleep(time.Second)
                            continue
                     }
                     if err != io.EOF && !strings.Contains(err.Error(), "use of closed network connection") {
                            log.Println("[ERROR] Permanent error when accepting new connections: ", err.Error())
                            return nil, err
                     }
                     return nil, io.EOF
              }
              if c == nil {
                     panic("BUG: net.Listener returned (nil, nil)")
              }
              //ConnectionTimeout 超时时间
              c.SetReadDeadline(time.Now().Add(time.Duration(ConnectionTimeout) * time.Second))
              //MaxConnSperIp 最大连接数
              if MaxConnSperIp > 0 {
                     pic := tc.wrapPerIPConn(c)
                     if pic == nil {
                            if time.Since(*lastPerIPErrorTime) > time.Minute {
                                   log.Println("[ERROR] The number of connections from ")
                                   *lastPerIPErrorTime = time.Now()
                            }
                            continue
                     }
                     c = pic
              }
              return c, nil
       }
}
func (tc *TcpServer) wrapPerIPConn(c net.Conn) net.Conn {
       ip := ipmanager.GetUint32IP(c)
       if ip == 0 {
              return c
       }
       n := tc.perIPConnCounter.Register(ip)
       //MaxConnSperIp 最大连接数
       if n > MaxConnSperIp {
              tc.perIPConnCounter.Unregister(ip)
              c.Close()
              return nil
       }
       return ipmanager.AcquirePerIPConn(c, ip, &tc.perIPConnCounter)
}

3.业务处理

func (tc *TcpServer) serve(conn net.Conn) {
       defer func() {
              conn.Close()
              if err := recover(); err != nil {
                     log.Println("readPacket", err)
                     return
              }
       }()
       uc := NewUserClient(conn)
       go readPacket(uc, uc.ChildStopChan)

       for {
              select {
              case message, ok := <-uc.PacketDataChan:
                     if !ok {
                            log.Println("packet is get error")
                            continue
                     }
                     switch message.GetPacketType() {
                     case packet.APPLICATION_SEND:
                            //业务处理
                            log.Println("业务处理", message)
                     default:
                            log.Println("invalid messageReceived msg:", message)
                            break
                     }
              case <-uc.LogOutStopChan:
                     goto LogOut
              }
       }
LogOut:
       defer func() {
              close(uc.ChildStopChan)
              close(uc.LogOutStopChan)
              close(uc.PacketDataChan)
       }()
       log.Println("LogOut close conn")
}

4.user client struct

type UserClient struct {
       Conn           net.Conn
       ChildStopChan  chan bool
       LogOutStopChan chan bool
       PacketDataChan chan packet.Packet
}

func NewUserClient(conn net.Conn) *UserClient {
       return &UserClient{Conn: conn,
              ChildStopChan:   make(chan bool, 1),
              LogOutStopChan:  make(chan bool, 1),
              PacketDataChan:  make(chan packet.Packet, 100),
       }
}


5.数据packet 解包

func readPacket(uc *UserClient, rStop <-chan bool) {
       defer func() {
              if err := recover(); err != nil {
                     log.Println("readPacket", err)
                     return
              }
       }()
       for {
              select {
              case <-rStop:
                     log.Println("readPacket", "readPacket get stop cmd")
                     goto Stop
              default:
                     pt, err := proto.ReadPacket(uc.Conn)
                     if err != nil {
                            log.Println("ReadPacket", err)
                            uc.LogOutStopChan <- true
                            goto Stop
                     }

                     //ConnectionTimeout 超时时间
                     uc.Conn.SetReadDeadline(time.Now().Add(time.Duration(ConnectionTimeout) * time.Second))
                     if pt != nil {
                            uc.PacketDataChan <- pt
                     }
              }
       }

Stop:
       log.Println("conn stop ...")
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值