-
Notifications
You must be signed in to change notification settings - Fork 9
/
tcp.go
155 lines (130 loc) · 2.82 KB
/
tcp.go
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
147
148
149
150
151
152
153
154
155
package core
import (
"fmt"
"github.com/gogather/com"
"io"
"log"
"net"
"os"
"regexp"
)
const (
BUFF_SIZE = 10
MAX_LCI = 100
)
type Client struct {
active bool
Conn net.Conn
cid int
login bool
}
var buff = make([]byte, BUFF_SIZE)
var cliTab = make(map[int]*Client)
var MARK string
/// close client connect from server
func (this *Client) Close() {
this.Conn.Close()
this.active = false
cliTab[this.cid] = nil
}
// send message to client and print in server console
func (this *Client) Write(str string) {
str = str + MARK
this.Conn.Write([]byte(str))
log.Println(str)
}
// set mark for login
// value: true for login, false for not login
func (this *Client) Login(value bool) {
this.login = value
}
func Parse(frame string, cli *Client) {
log.Println(frame)
json, err := com.JsonDecode(frame)
if err != nil {
log.Println(err)
} else {
data := json.(map[string]interface{})
actonName, ok := data["action"].(string)
if !ok {
cli.Write("invalid request, action name is not exist.")
return
}
// 如果不是登录请求,并且用户处于未登录状态,禁止通行
if actonName != "login" {
if !cli.login {
cli.Write("you have not login.")
return
}
}
RouterMap[actonName].Tcp(data, cli)
}
}
func handleError(err error, tcpConn net.Conn) {
if err != nil {
fmt.Fprintf(os.Stderr, "Client error: %s\n", err.Error())
if tcpConn != nil {
tcpConn.Close()
}
}
}
func handleConnection(tcpConn net.Conn, cid int) {
frame := ""
if tcpConn == nil {
return
}
cli := &Client{true, tcpConn, cid, false}
cliTab[cid] = cli
fmt.Println("Connected! Remote address is " + tcpConn.LocalAddr().String())
tcpConn.Write([]byte("Connected! Remote address is " + tcpConn.LocalAddr().String() + "/" + MARK + "#"))
for {
n, err := tcpConn.Read(buff)
if err == io.EOF {
fmt.Printf("The RemoteAddr:%s is closed!\n", tcpConn.RemoteAddr().String())
return
}
// Accident exit
handleError(err, tcpConn)
if tcpConn != nil && err != nil {
return
}
if n > 0 {
frame = frame + string(buff[:n])
reg := regexp.MustCompile(MARK)
if len(reg.FindAllString(string(buff[:n]), -1)) > 0 {
// get the json
frame = reg.ReplaceAllString(frame, "")
// submit json task
Parse(frame, cli)
frame = ""
// if connection is inactive[closed by server, jump out of cycle
if !cli.active {
return
}
}
}
}
}
func TcpStart() {
i := 0
ln, err := net.Listen("tcp", ":1004")
handleError(err, nil)
if len(os.Args) > 1 && os.Args[1] == "debug" {
MARK = "#"
} else {
MARK = "\003"
}
for {
conn, err := ln.Accept()
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
continue
}
i += 1
if i > MAX_LCI {
fmt.Println("reached max client limit, server stoped.")
return
}
go handleConnection(conn, i)
}
}