forked from andeya/erpc
/
client.go
153 lines (127 loc) · 3.21 KB
/
client.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
package teleport
import (
"log"
"net"
"time"
)
// 客户端专有成员
type tpClient struct {
// 客户端模式下,控制是否为短链接
short bool
// 强制终止客户端
mustClose bool
// 服务器UID
serverUID string
}
// 启动客户端模式
func (self *TP) Client(serverAddr string, port string, isShort ...bool) {
if len(isShort) > 0 && isShort[0] {
self.tpClient.short = true
} else if self.timeout == 0 {
// 默认心跳间隔时长
self.timeout = DEFAULT_TIMEOUT_C
}
// 服务器UID默认为常量DEFAULT_SERVER_UID
if self.tpClient.serverUID == "" {
self.tpClient.serverUID = DEFAULT_SERVER_UID
}
self.reserveAPI()
self.mode = CLIENT
// 设置端口
if port != "" {
self.port = port
} else {
self.port = DEFAULT_PORT
}
self.serverAddr = serverAddr
self.tpClient.mustClose = false
go self.apiHandle()
go self.client()
}
// ***********************************************功能实现*************************************************** \\
// 以客户端模式启动
func (self *TP) client() {
if !self.short {
log.Println(" * —— 正在连接服务器……")
}
RetryLabel:
conn, err := net.Dial("tcp", self.serverAddr+self.port)
if err != nil {
if self.tpClient.mustClose {
self.tpClient.mustClose = false
return
}
time.Sleep(LOOP_TIMEOUT)
goto RetryLabel
}
// log.Printf(" * —— 成功连接到服务器:%v ——", conn.RemoteAddr().String())
// 开启该连接处理协程(读写两条协程)
self.cGoConn(conn)
// 与服务器意外断开后自动重拨
if !self.short {
for self.CountNodes() > 0 {
time.Sleep(LOOP_TIMEOUT)
}
// 判断是否为意外断开
if _, ok := self.connPool[self.tpClient.serverUID]; ok {
goto RetryLabel
}
}
}
// 为连接开启读写两个协程
func (self *TP) cGoConn(conn net.Conn) {
remoteAddr, connect := NewConnect(conn, self.connBufferLen, self.connWChanCap)
// 添加连接到节点池
self.connPool[self.tpClient.serverUID] = connect
if self.uid == "" {
// 设置默认UID
self.uid = conn.LocalAddr().String()
}
if !self.short {
self.send(NewNetData(self.uid, self.tpClient.serverUID, IDENTITY, ""))
log.Printf(" * —— 成功连接到服务器:%v ——", remoteAddr)
} else {
connect.Short = true
}
// 标记连接已经正式生效可用
self.connPool[self.tpClient.serverUID].Usable = true
// 开启读写双工协程
go self.cReader(self.tpClient.serverUID)
go self.cWriter(self.tpClient.serverUID)
}
// 客户端读数据
func (self *TP) cReader(nodeuid string) {
// 退出时关闭连接,删除连接池中的连接
defer func() {
self.closeConn(nodeuid, true)
}()
var conn = self.getConn(nodeuid)
for {
if !self.read(conn) {
break
}
}
}
// 客户端发送数据
func (self *TP) cWriter(nodeuid string) {
// 退出时关闭连接,删除连接池中的连接
defer func() {
self.closeConn(nodeuid, true)
}()
var conn = self.getConn(nodeuid)
for conn != nil {
if self.short {
self.send(<-conn.WriteChan)
continue
}
timing := time.After(self.timeout)
data := new(NetData)
select {
case data = <-conn.WriteChan:
case <-timing:
// 保持心跳
data = NewNetData(self.uid, nodeuid, HEARTBEAT, "")
}
self.send(data)
}
}