net.go
3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main
import (
"bytes"
"common/logger"
//pb "common/protocol"
pb "WorldTester/pb"
"encoding/binary"
"errors"
"log"
"net"
"reflect"
"time"
"github.com/golang/protobuf/proto"
)
type MessageHandler func(conn net.Conn, header pb.MessageHeader, msg interface{})
type MessageInfo struct {
msgType reflect.Type
msgHandler MessageHandler
}
var (
msg_map = make(map[pb.MSGID]MessageInfo)
Max_Message_Size uint16 = 4096
)
func RegisterMessage(msgid pb.MSGID, msg interface{}, handler MessageHandler) {
var info MessageInfo
info.msgType = reflect.TypeOf(msg.(proto.Message))
info.msgHandler = handler
msg_map[msgid] = info
}
func getTcpClient(uid uint32) net.Conn {
conn, err := net.Dial("tcp", server_addr)
if err != nil {
logger.Info("connect server:%+v error:%=v", server_addr, err.Error())
log.Println("connect server:%+v error:%=v", server_addr, err.Error())
return nil
}
logger.Info("connect server success! for uid:%+v addr:%v", uid, server_addr)
log.Println("connect server success! for uid:%+v addr:%v", uid, server_addr)
return conn
}
/*
func clientSendLoop(conn net.Conn) {
sms := make([]byte, 128)
_ = sms
for {
fmt.Print("\nenter command:")
// _, err := fmt.Scan(&sms)
reader := bufio.NewReader(os.Stdin)
strBytes, _, err := reader.ReadLine()
if err != nil {
fmt.Println("invalid input:", err.Error())
break
}
handleCommand(conn, string(strBytes))
}
fmt.Println("send loop exist")
}
*/
func clientRecvLoop(player *PlayerInfo) {
tmp := make([]byte, 10240)
buf := make([]byte, 0, 10240)
var buf_len uint32
defer player.conn.Close()
for {
player.conn.SetReadDeadline(time.Now().Add(time.Second))
n, err := player.conn.Read(tmp)
if err != nil {
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
checkPlayer(player)
continue
}
logger.Info("recv conn error:%+v", err)
break
}
buf = append(buf, tmp[:n]...)
buf_len += uint32(n)
for buf_len >= uint32(Min_Message_Size) {
el, err := handleBuffer(player.conn, buf, buf_len)
if err != nil {
logger.Info("handler buffer error:%+v", err)
break
} else {
buf_len -= el
buf = buf[el:]
}
}
checkPlayer(player)
}
logger.Info("recv loop exist for uid:%v conn:%v", player.uid, player.conn)
}
func handleBuffer(conn net.Conn, buffer []byte, size uint32) (eat_len uint32, err error) {
var header pb.MessageHeader
rd := bytes.NewReader(buffer[0:Min_Message_Size])
binary.Read(rd, binary.BigEndian, &header)
if header.PackageLen > Max_Message_Size {
logger.Info("error got invalid message size:%+v", header.PackageLen)
eat_len = size
err = nil
return
}
if uint32(header.PackageLen) > size {
logger.Info("error message not enough, buffer size:%v, pakcet len:%v header:%+v\n",
size, header.PackageLen, header)
eat_len = 0
err = errors.New("error not enough")
return
}
dispatchRawData(conn, header, buffer[Min_Message_Size:header.PackageLen])
eat_len = uint32(header.PackageLen)
err = nil
return
}
func dispatchRawData(conn net.Conn, header pb.MessageHeader, data []byte) {
logger.Info("<-- dispatch new message header:%+v\n", header)
msgid := pb.MSGID(header.MsgID)
if info, ok := msg_map[msgid]; ok {
msg := reflect.New(info.msgType.Elem()).Interface()
err := proto.Unmarshal(data, msg.(proto.Message))
if err != nil {
return
}
info.msgHandler(conn, header, msg)
return
} else {
logger.Info("invalid msgid from server:%+v", msgid)
}
}