Files
origin/network/tcpsocketserver.go
2020-03-13 15:37:49 +08:00

332 lines
6.9 KiB
Go

package network
import (
"bufio"
"encoding/binary"
"fmt"
"github.com/duanhf2012/origin/service"
"github.com/duanhf2012/origin/util"
"github.com/golang/protobuf/proto"
"io"
"net"
"unsafe"
"os"
"time"
)
type ITcpSocketServerReciver interface {
OnConnected(pClient *SClient)
OnDisconnect(pClient *SClient)
OnRecvMsg(pClient *SClient, pPack *MsgBasePack)
}
type SClient struct {
id uint64
conn net.Conn
recvPack *util.SyncQueue
sendPack *util.SyncQueue
tcpserver *TcpSocketServer
remoteip string
starttime int64
bClose bool
}
type TcpSocketServer struct {
listenAddr string //ip:port
mapClient util.Map
MaxRecvPackSize uint16
MaxSendPackSize uint16
iReciver ITcpSocketServerReciver
nodelay bool
}
type MsgBasePack struct {
PackSize uint16
PackType uint16
Body []byte
StartTime time.Time
}
func (slf *TcpSocketServer) Register(listenAddr string,iReciver ITcpSocketServerReciver){
slf.listenAddr = listenAddr
slf.iReciver = iReciver
}
func (slf *TcpSocketServer) Start(){
slf.MaxRecvPackSize = 2048
slf.MaxSendPackSize = 40960
util.Go(slf.listenServer)
}
func (slf *TcpSocketServer) listenServer(){
slf.nodelay = true
listener, err := net.Listen("tcp", slf.listenAddr)
if err != nil {
service.GetLogger().Printf(service.LEVER_FATAL, "TcpSocketServer Listen error %+v",err)
os.Exit(1)
}
var clientId uint64
for {
conn, aerr := listener.Accept()
if aerr != nil {
service.GetLogger().Printf(service.LEVER_FATAL, "TcpSocketServer accept error %+v",aerr)
continue
}
if slf.nodelay {
//conn.(ifaceSetNoDelay)
}
for {
clientId += 1
if slf.mapClient.Get(clientId)!= nil {
continue
}
sc :=&SClient{id:clientId,conn:conn,tcpserver:slf,remoteip:conn.RemoteAddr().String(),starttime:time.Now().UnixNano(),
recvPack:util.NewSyncQueue(),sendPack:util.NewSyncQueue()}
slf.mapClient.Set(clientId,sc)
util.Go(sc.listendata)
//收来自客户端数据
util.Go(sc.onrecv)
//发送数据队列
util.Go(sc.onsend)
break
}
}
}
func (slf *TcpSocketServer) Close(clientid uint64) error {
pClient := slf.mapClient.Get(clientid)
if pClient == nil {
return fmt.Errorf("clientid %d is not in connect pool.",clientid)
}
pClient.(*SClient).Close()
return nil
}
func (slf *TcpSocketServer) SendMsg(clientid uint64,packtype uint16,message proto.Message) error{
pClient := slf.mapClient.Get(clientid)
if pClient == nil {
return fmt.Errorf("clientid %d is not in connect pool.",clientid)
}
return pClient.(*SClient).SendMsg(packtype,message)
}
func (slf *TcpSocketServer) Send(clientid uint64,pack *MsgBasePack) error{
pClient := slf.mapClient.Get(clientid)
if pClient == nil {
return fmt.Errorf("clientid %d is not in connect pool.",clientid)
}
return pClient.(*SClient).Send(pack)
}
func (slf *SClient) listendata(){
defer func() {
slf.Close()
slf.tcpserver.mapClient.Del(slf.id)
slf.tcpserver.iReciver.OnDisconnect(slf)
service.GetLogger().Printf(service.LEVER_DEBUG, "clent id %d return listendata...",slf.id)
}()
slf.tcpserver.iReciver.OnConnected(slf)
//获取一个连接的reader读取流
reader := bufio.NewReader(slf.conn)
//临时接受数据的buff
var buff []byte //tmprecvbuf
var tmpbuff []byte
var buffDataSize uint16
tmpbuff = make([]byte,2048)
//解析包数据
var pack MsgBasePack
for {
n,err := reader.Read(tmpbuff)
if err != nil || err == io.EOF {
service.GetLogger().Printf(service.LEVER_INFO, "clent id %d is disconnect %+v",slf.id,err)
return
}
buff = append(buff,tmpbuff[:n]...)
buffDataSize += uint16(n)
if buffDataSize> slf.tcpserver.MaxRecvPackSize {
service.GetLogger().Print(service.LEVER_WARN,"recv client id %d data size %d is over %d",slf.id,buffDataSize,slf.tcpserver.MaxRecvPackSize)
return
}
fillsize,bfillRet,fillhead := pack.FillData(buff,buffDataSize)
//提交校验头
if fillhead == true {
if pack.PackSize>slf.tcpserver.MaxRecvPackSize {
service.GetLogger().Printf(service.LEVER_WARN, "VerifyPackType error clent id %d is disconnect %d,%d",slf.id,pack.PackType, pack.PackSize)
return
}
}
if bfillRet == true {
slf.recvPack.Push(pack)
pack = MsgBasePack{}
}
if fillsize>0 {
buff = append(buff[fillsize:])
buffDataSize -= fillsize
}
}
}
func (slf *MsgBasePack) Bytes() []byte{
var bRet []byte
bRet = make([]byte,4)
binary.BigEndian.PutUint16(bRet,slf.PackSize)
binary.BigEndian.PutUint16(bRet[2:],slf.PackType)
bRet = append(bRet,slf.Body...)
return bRet
}
//返回值:填充多少字节,是否完成,是否填充头
func (slf *MsgBasePack) FillData(bdata []byte,datasize uint16) (uint16,bool,bool) {
var fillsize uint16
fillhead := false
//解包头
if slf.PackSize ==0 {
if datasize < 4 {
return 0,false,fillhead
}
slf.PackSize= binary.BigEndian.Uint16(bdata[:2])
slf.PackType= binary.BigEndian.Uint16(bdata[2:4])
fillsize += 4
fillhead = true
}
//解包体
if slf.PackSize>0 && datasize+4>=slf.PackSize {
slf.Body = append(slf.Body, bdata[fillsize:slf.PackSize]...)
fillsize += (slf.PackSize - fillsize)
return fillsize,true,fillhead
}
return fillsize,false,fillhead
}
func (slf *MsgBasePack) Clear() {
}
func (slf *MsgBasePack) Make(packtype uint16,data []byte) {
slf.PackType = packtype
slf.Body = data
slf.PackSize = uint16(unsafe.Sizeof(slf.PackType)*2)+uint16(len(data))
}
func (slf *SClient) Send(pack *MsgBasePack) error {
if slf.bClose == true {
return fmt.Errorf("client id %d is close!",slf.id)
}
slf.sendPack.Push(pack)
return nil
}
func (slf *SClient) SendMsg(packtype uint16,message proto.Message) error{
if slf.bClose == true {
return fmt.Errorf("client id %d is close!",slf.id)
}
var msg MsgBasePack
data,err := proto.Marshal(message)
if err != nil {
return err
}
msg.Make(packtype,data)
slf.sendPack.Push(&msg)
return nil
}
func (slf *SClient) onsend(){
defer func() {
slf.Close()
service.GetLogger().Printf(service.LEVER_DEBUG, "clent id %d return onsend...",slf.id)
}()
for {
pack,ok := slf.sendPack.TryPop()
if slf.bClose == true {
break
}
if ok == false || pack == nil {
time.Sleep(time.Millisecond*1)
continue
}
pPackData := pack.(*MsgBasePack)
_,e := slf.conn.Write(pPackData.Bytes())
if e!=nil {
service.GetLogger().Printf(service.LEVER_DEBUG, "clent id %d write error...",slf.id)
return
}
//fmt.Print("xxxxxxxxxxxxxxx:",n,e)
}
}
func (slf *SClient) onrecv(){
defer func() {
slf.Close()
service.GetLogger().Printf(service.LEVER_DEBUG, "clent id %d return onrecv...",slf.id)
}()
for {
pack,ok := slf.recvPack.TryPop()
if slf.bClose == true {
break
}
if ok == false || pack == nil {
time.Sleep(time.Millisecond*1)
continue
}
pMsg := pack.(MsgBasePack)
slf.tcpserver.iReciver.OnRecvMsg(slf,&pMsg)
}
}
func (slf *SClient) Close(){
if slf.bClose == false {
slf.conn.Close()
slf.bClose = true
slf.recvPack.Close()
slf.sendPack.Close()
}
}
func (slf *SClient) GetId() uint64{
return slf.id
}