-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.go
More file actions
259 lines (234 loc) · 7.04 KB
/
Copy pathserver.go
File metadata and controls
259 lines (234 loc) · 7.04 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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
package GeeRPC
import (
"GeeRPC/codec"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net"
"net/http"
"reflect"
"strings"
"sync"
"time"
)
const MagicNumber = 0x3bef5c
const (
connected = "200 Connected to Gee RPC"
defaultRPCPath = "/_geerpc_"
defaultDebugPath = "/debug/geerpc"
)
// Option 首部选项
type Option struct {
// MagicNumber 用于标记请求
MagicNumber int
// CodecType 编解码器类型
CodecType codec.Type
// ConnectTimeout 连接超时时间
ConnectTimeout time.Duration // 0 means no limit
// HandleTimeout 处理超时时间
HandleTimeout time.Duration // 0 means no limit
}
var DefaultOption = &Option{
MagicNumber: MagicNumber,
CodecType: codec.GobType, // 默认编解码器为gob
ConnectTimeout: time.Second * 10, // 默认连接超时时间为10s
}
// Server represents an RPC Server
type Server struct {
// serviceMap is the registry of service
serviceMap sync.Map
}
func NewServer() *Server {
return &Server{}
}
var DefaultServer = NewServer()
func Register(rcvr interface{}) error {
return DefaultServer.Register(rcvr)
}
// Register publishes in the server the set of methods of the receiver value
func (server *Server) Register(rcvr interface{}) error {
s := newService(rcvr) // 创建服务
if _, dup := server.serviceMap.LoadOrStore(s.name, s); dup {
return fmt.Errorf("rpc: service already defined: %s", s.name)
}
return nil
}
// findService 查找服务,通过服务名找到服务
func (server *Server) findService(serviceMethod string) (svc *service, mtype *methodType, err error) {
dot := strings.LastIndex(serviceMethod, ".") // 找到最后一个点的位置
if dot < 0 {
err = errors.New("rpc server: service/method request ill-formed: " + serviceMethod)
return
}
// 通过最后一个点将服务名和方法名分开
serviceName, methodName := serviceMethod[:dot], serviceMethod[dot+1:]
// 通过服务名找到服务
svci, ok := server.serviceMap.Load(serviceName)
if !ok {
err = errors.New("rpc server: can't find service " + serviceName)
return
}
// 通过反射找到方法
svc = svci.(*service)
mtype = svc.method[methodName]
if mtype == nil {
err = errors.New("rpc server: can't find method " + methodName)
}
return
}
func (server *Server) Accept(lis net.Listener) {
for {
conn, err := lis.Accept()
if err != nil {
log.Println("RPC Server Accept Error:", err)
return
}
log.Printf("接收到客户端连接 {Local Addr: %s; Remote Addr: %s\n ", conn.LocalAddr().String(), conn.RemoteAddr().String())
go server.ServeConn(conn)
}
}
func Accept(lis net.Listener) {
DefaultServer.Accept(lis)
}
// ServeConn 服务端处理连接
func (server *Server) ServeConn(conn io.ReadWriteCloser) {
defer func() { conn.Close() }()
var opt Option
if err := json.NewDecoder(conn).Decode(&opt); err != nil { // TODO EOF error
log.Println("RPC Server option error: ", err)
return
}
if opt.MagicNumber != MagicNumber {
log.Printf("RPC Server invaild magic number: %x\n", opt.MagicNumber)
return
}
f := codec.NewCodecFuncMap[opt.CodecType]
if f == nil {
log.Printf("RPC Server invaild codec type %s\n", opt.CodecType)
}
server.ServerCodec(f(conn), &opt)
}
var invalidRequest = struct{}{}
func (server *Server) ServerCodec(cc codec.Codec, opt *Option) {
sending := new(sync.Mutex) // make sure to send a complete response
wg := new(sync.WaitGroup) // wait until all request are handled
for {
req, err := server.readRequest(cc)
if err != nil {
if req == nil {
break // it's not possible to recover, so close the connection
}
req.h.Error = err.Error()
server.sendResponse(cc, req.h, invalidRequest, sending)
continue
}
wg.Add(1)
go server.handleRequest(cc, req, sending, wg, opt.HandleTimeout)
}
wg.Wait()
_ = cc.Close()
}
// request stores all information of a call
type request struct {
h *codec.Header // header of request
argv, replyv reflect.Value // argv and replyv of request
mtype *methodType // type of request
svc *service // service of request
}
func (server *Server) readRequest(cc codec.Codec) (*request, error) {
h, err := server.readRequestHeader(cc)
if err != nil {
return nil, err
}
req := &request{h: h}
req.svc, req.mtype, err = server.findService(h.ServiceMethod)
if err != nil {
return req, err
}
req.argv = req.mtype.newArgv()
req.replyv = req.mtype.newReplyv()
argvi := req.argv.Interface()
if req.argv.Type().Kind() != reflect.Ptr {
argvi = req.argv.Addr().Interface() // 如果不是指针类型,那么取地址
}
if err = cc.ReadBody(argvi); err != nil {
log.Println("rpc server: read argv err:", err)
return req, err
}
return req, nil
}
func (server *Server) readRequestHeader(cc codec.Codec) (*codec.Header, error) {
var h codec.Header
if err := cc.ReadHeader(&h); err != nil {
if err != io.EOF && err != io.ErrUnexpectedEOF {
log.Println("rpc server: read header error:", err)
}
return nil, err
}
return &h, nil
}
func (server *Server) sendResponse(cc codec.Codec, h *codec.Header, body interface{}, sending *sync.Mutex) {
sending.Lock()
defer sending.Unlock()
if err := cc.Write(h, body); err != nil {
log.Println("rpc server: write response error:", err)
}
}
func (server *Server) handleRequest(cc codec.Codec, req *request, sending *sync.Mutex, wg *sync.WaitGroup, timeout time.Duration) {
defer wg.Done()
called := make(chan struct{}) // call 方法是否被调用
sent := make(chan struct{}) // call 方法是否被发送
go func() {
err := req.svc.call(req.mtype, req.argv, req.replyv)
called <- struct{}{}
if err != nil {
req.h.Error = err.Error()
server.sendResponse(cc, req.h, invalidRequest, sending)
sent <- struct{}{}
return
}
server.sendResponse(cc, req.h, req.replyv.Interface(), sending)
sent <- struct{}{}
}()
if timeout == 0 {
<-called
<-sent
return
}
select {
case <-time.After(timeout):
req.h.Error = fmt.Sprintf("rpc server: request handle timeout: expect within %s", timeout)
server.sendResponse(cc, req.h, invalidRequest, sending)
case <-called:
<-sent
}
}
// ServeHTTP implements an http.Handler that answers RPC requests.
func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if req.Method != "CONNECT" {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusMethodNotAllowed)
_, _ = io.WriteString(w, "405 must CONNECT\n")
return
}
conn, _, err := w.(http.Hijacker).Hijack() // 获取底层的网络连接, 用于后续的RPC通信
if err != nil {
log.Println("rpc hijacking", req.RemoteAddr, ":", err.Error())
return
}
// 通知客户端连接建立成功
_, _ = io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
server.ServeConn(conn) // 服务端处理连接
}
// HandleHTTP 注册一个HTTP处理程序以处理rpcPath上的RPC消息。
func (server *Server) HandleHTTP() {
http.Handle(defaultRPCPath, server)
http.Handle(defaultDebugPath, debugHTTP{server})
log.Println("rpc server debug path:", defaultDebugPath)
}
// HandleHTTP 在rpcPath上注册一个HTTP处理程序以处理RPC消息
func HandleHTTP() {
DefaultServer.HandleHTTP()
}