mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-03 22:45:13 +08:00
332 lines
6.9 KiB
Go
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
|
|
}
|