trpc.group/trpc-go/trpc-go@v1.0.3/transport/example_test.go (about) 1 // 2 // 3 // Tencent is pleased to support the open source community by making tRPC available. 4 // 5 // Copyright (C) 2023 THL A29 Limited, a Tencent company. 6 // All rights reserved. 7 // 8 // If you have downloaded a copy of the tRPC source code from Tencent, 9 // please note that tRPC source code is licensed under the Apache 2.0 License, 10 // A copy of the Apache 2.0 License is included in this file. 11 // 12 // 13 14 package transport_test 15 16 import ( 17 "bytes" 18 "context" 19 "encoding/binary" 20 "encoding/json" 21 "errors" 22 "fmt" 23 "io" 24 "log" 25 "time" 26 27 "trpc.group/trpc-go/trpc-go/errs" 28 29 "trpc.group/trpc-go/trpc-go/codec" 30 "trpc.group/trpc-go/trpc-go/transport" 31 ) 32 33 var defaultStreamID uint32 = 100 34 35 func clientInvokeServer(network string) { 36 go func() { 37 err := transport.ListenAndServe( 38 transport.WithListenNetwork(network), 39 transport.WithListenAddress(":8888"), 40 transport.WithHandler(&simpleHandler{}), 41 transport.WithServerFramerBuilder(&framerBuilder{}), 42 ) 43 44 if err != nil { 45 log.Fatalln(err) 46 } 47 }() 48 49 time.Sleep(time.Millisecond * 10) 50 51 ctx, f := context.WithTimeout(context.Background(), 3*time.Second) 52 defer f() 53 req := &helloRequest{ 54 Name: "trpc", 55 Msg: "HelloWorld", 56 } 57 58 data, err := json.Marshal(req) 59 if err != nil { 60 log.Fatalln(err) 61 } 62 lenData := make([]byte, 4) 63 binary.BigEndian.PutUint32(lenData, uint32(len(data))) 64 65 reqData := append(lenData, data...) 66 67 rspData, err := transport.RoundTrip(ctx, reqData, transport.WithDialNetwork(network), 68 transport.WithDialAddress(":8888"), 69 transport.WithClientFramerBuilder(&framerBuilder{})) 70 if nil != err { 71 log.Fatalf("RoundTip Error : %v", err) 72 } 73 74 length := binary.BigEndian.Uint32(rspData[:4]) 75 76 helloRsp := &helloResponse{} 77 err = json.Unmarshal(rspData[4:4+length], helloRsp) 78 if err != nil { 79 log.Fatalln(err) 80 } 81 82 fmt.Println(helloRsp) 83 84 } 85 86 func UDP4TransportExample() { 87 clientInvokeServer("udp4") 88 // Output: 89 // &{trpc HelloWorld 0} 90 } 91 92 func TCPTransportExample() { 93 clientInvokeServer("tcp") 94 // Output: 95 // &{trpc HelloWorld 0} 96 } 97 98 type helloRequest struct { 99 Name string 100 Msg string 101 } 102 103 type helloResponse struct { 104 Name string 105 Msg string 106 Code int 107 } 108 109 // timeoutError simulates network timeout error. 110 type timeoutError struct { 111 } 112 113 // Error implements error. 114 func (t *timeoutError) Error() string { 115 return "Timeout" 116 } 117 118 // Timeout checks whether is it a timeout error. 119 func (t *timeoutError) Timeout() bool { 120 return true 121 } 122 123 // Temporary checks whether is it a temporary error. 124 func (t *timeoutError) Temporary() bool { 125 return true 126 } 127 128 type framerBuilder struct { 129 errSet bool 130 err error 131 safe bool 132 } 133 134 // SetError sets frameBuilder error. 135 func (fb *framerBuilder) SetError(err error) { 136 fb.errSet = true 137 fb.err = err 138 } 139 140 func (fb *framerBuilder) ClearError() { 141 fb.errSet = false 142 fb.err = nil 143 } 144 145 func (fb *framerBuilder) New(r io.Reader) codec.Framer { 146 return &framer{r: r, fb: fb} 147 } 148 149 type framer struct { 150 fb *framerBuilder 151 r io.Reader 152 } 153 154 func (f *framer) ReadFrame() ([]byte, error) { 155 if f.fb.errSet { 156 return nil, f.fb.err 157 } 158 var lenData [4]byte 159 160 _, err := io.ReadFull(f.r, lenData[:]) 161 if err != nil { 162 return nil, err 163 } 164 165 length := binary.BigEndian.Uint32(lenData[:]) 166 167 msg := make([]byte, len(lenData)+int(length)) 168 copy(msg, lenData[:]) 169 170 _, err = io.ReadFull(f.r, msg[len(lenData):]) 171 if err != nil { 172 return nil, err 173 } 174 175 return msg, nil 176 } 177 178 func (f *framer) IsSafe() bool { 179 return f.fb.safe 180 } 181 182 type errorHandler struct{} 183 184 func (h *errorHandler) Handle(ctx context.Context, req []byte) ([]byte, error) { 185 return nil, errors.New("handle error") 186 } 187 188 type simpleHandler struct{} 189 190 func (h *simpleHandler) Handle(ctx context.Context, reqdata []byte) ([]byte, error) { 191 192 helloReq := &helloRequest{} 193 helloRsp := &helloResponse{} 194 195 if len(reqdata) < 4 { 196 return nil, errors.New("reqData format error") 197 } 198 199 json.Unmarshal(reqdata[4:], helloReq) 200 201 helloRsp.Name = helloReq.Name 202 helloRsp.Msg = helloReq.Msg 203 data, _ := json.Marshal(helloRsp) 204 buf := new(bytes.Buffer) 205 binary.Write(buf, binary.BigEndian, uint32(len(data))) 206 binary.Write(buf, binary.BigEndian, data) 207 return buf.Bytes(), nil 208 } 209 210 type echoHandler struct{} 211 212 func (h *echoHandler) Handle(ctx context.Context, req []byte) ([]byte, error) { 213 rsp := make([]byte, len(req)) 214 copy(rsp, req) 215 return rsp, nil 216 } 217 218 type echoStreamHandler struct{} 219 220 func (h *echoStreamHandler) Handle(ctx context.Context, req []byte) ([]byte, error) { 221 rsp := make([]byte, len(req)) 222 copy(rsp, req) 223 return rsp, errs.ErrServerNoResponse 224 }