github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/rpc/client.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:45</date>
    10  //</624342663759400960>
    11  
    12  
    13  package rpc
    14  
    15  import (
    16  	"bytes"
    17  	"container/list"
    18  	"context"
    19  	"encoding/json"
    20  	"errors"
    21  	"fmt"
    22  	"net"
    23  	"net/url"
    24  	"os"
    25  	"reflect"
    26  	"strconv"
    27  	"strings"
    28  	"sync"
    29  	"sync/atomic"
    30  	"time"
    31  
    32  	"github.com/ethereum/go-ethereum/log"
    33  )
    34  
    35  var (
    36  	ErrClientQuit                = errors.New("client is closed")
    37  	ErrNoResult                  = errors.New("no result in JSON-RPC response")
    38  	ErrSubscriptionQueueOverflow = errors.New("subscription queue overflow")
    39  )
    40  
    41  const (
    42  //超时
    43  	tcpKeepAliveInterval = 30 * time.Second
    44  defaultDialTimeout   = 10 * time.Second //如果上下文没有截止时间,则在拨号时使用
    45  defaultWriteTimeout  = 10 * time.Second //如果上下文没有截止时间,则用于调用
    46  subscribeTimeout     = 5 * time.Second  //总超时eth_subscribe,rpc_模块调用
    47  )
    48  
    49  const (
    50  //当订阅服务器无法跟上时,将删除订阅。
    51  //
    52  //这可以通过为通道提供足够大的缓冲区来解决,
    53  //但这在文件中可能不方便也很难解释。另一个问题是
    54  //缓冲通道是指即使不需要缓冲区,缓冲区也是静态的。
    55  //大部分时间。
    56  //
    57  //这里采用的方法是维护每个订阅的链表缓冲区
    58  //按需缩小。如果缓冲区达到以下大小,则订阅为
    59  //下降。
    60  	maxClientSubscriptionBuffer = 20000
    61  )
    62  
    63  //batchelem是批处理请求中的元素。
    64  type BatchElem struct {
    65  	Method string
    66  	Args   []interface{}
    67  //结果未显示在此字段中。结果必须设置为
    68  //所需类型的非零指针值,否则响应将为
    69  //丢弃的。
    70  	Result interface{}
    71  //如果服务器返回此请求的错误,或如果
    72  //解组为结果失败。未设置I/O错误。
    73  	Error error
    74  }
    75  
    76  //此类型的值可以是JSON-RPC请求、通知、成功响应或
    77  //错误响应。它是哪一个取决于田地。
    78  type jsonrpcMessage struct {
    79  	Version string          `json:"jsonrpc"`
    80  	ID      json.RawMessage `json:"id,omitempty"`
    81  	Method  string          `json:"method,omitempty"`
    82  	Params  json.RawMessage `json:"params,omitempty"`
    83  	Error   *jsonError      `json:"error,omitempty"`
    84  	Result  json.RawMessage `json:"result,omitempty"`
    85  }
    86  
    87  func (msg *jsonrpcMessage) isNotification() bool {
    88  	return msg.ID == nil && msg.Method != ""
    89  }
    90  
    91  func (msg *jsonrpcMessage) isResponse() bool {
    92  	return msg.hasValidID() && msg.Method == "" && len(msg.Params) == 0
    93  }
    94  
    95  func (msg *jsonrpcMessage) hasValidID() bool {
    96  	return len(msg.ID) > 0 && msg.ID[0] != '{' && msg.ID[0] != '['
    97  }
    98  
    99  func (msg *jsonrpcMessage) String() string {
   100  	b, _ := json.Marshal(msg)
   101  	return string(b)
   102  }
   103  
   104  //客户端表示到RPC服务器的连接。
   105  type Client struct {
   106  	idCounter   uint32
   107  	connectFunc func(ctx context.Context) (net.Conn, error)
   108  	isHTTP      bool
   109  
   110  //WRITECONN只能安全地访问外部调度,使用
   111  //写入锁定保持。通过发送
   112  //请求操作并通过发送发送完成释放。
   113  	writeConn net.Conn
   114  
   115  //派遣
   116  	close       chan struct{}
   117  didQuit     chan struct{}                  //客户端退出时关闭
   118  reconnected chan net.Conn                  //写入/重新连接发送新连接的位置
   119  readErr     chan error                     //读取错误
   120  readResp    chan []*jsonrpcMessage         //读取的有效消息
   121  requestOp   chan *requestOp                //用于注册响应ID
   122  sendDone    chan error                     //信号写入完成,释放写入锁定
   123  respWait    map[string]*requestOp          //主动请求
   124  subs        map[string]*ClientSubscription //活动订阅
   125  }
   126  
   127  type requestOp struct {
   128  	ids  []json.RawMessage
   129  	err  error
   130  resp chan *jsonrpcMessage //接收最多len(id)响应
   131  sub  *ClientSubscription  //仅为ethsubscribe请求设置
   132  }
   133  
   134  func (op *requestOp) wait(ctx context.Context) (*jsonrpcMessage, error) {
   135  	select {
   136  	case <-ctx.Done():
   137  		return nil, ctx.Err()
   138  	case resp := <-op.resp:
   139  		return resp, op.err
   140  	}
   141  }
   142  
   143  //拨号为给定的URL创建新的客户端。
   144  //
   145  //当前支持的URL方案有“http”、“https”、“ws”和“wss”。如果RAWURL是
   146  //没有URL方案的文件名,使用Unix建立本地套接字连接
   147  //支持的平台上的域套接字和Windows上的命名管道。如果你想
   148  //配置传输选项,使用dialHTTP、dialWebSocket或dialIPC。
   149  //
   150  //对于WebSocket连接,原点设置为本地主机名。
   151  //
   152  //如果连接丢失,客户端将自动重新连接。
   153  func Dial(rawurl string) (*Client, error) {
   154  	return DialContext(context.Background(), rawurl)
   155  }
   156  
   157  //DialContext创建一个新的RPC客户端,就像Dial一样。
   158  //
   159  //上下文用于取消或超时初始连接建立。它确实
   160  //不影响与客户的后续交互。
   161  func DialContext(ctx context.Context, rawurl string) (*Client, error) {
   162  	u, err := url.Parse(rawurl)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  	switch u.Scheme {
   167  	case "http", "https":
   168  		return DialHTTP(rawurl)
   169  	case "ws", "wss":
   170  		return DialWebsocket(ctx, rawurl, "")
   171  	case "stdio":
   172  		return DialStdIO(ctx)
   173  	case "":
   174  		return DialIPC(ctx, rawurl)
   175  	default:
   176  		return nil, fmt.Errorf("no known transport for URL scheme %q", u.Scheme)
   177  	}
   178  }
   179  
   180  type StdIOConn struct{}
   181  
   182  func (io StdIOConn) Read(b []byte) (n int, err error) {
   183  	return os.Stdin.Read(b)
   184  }
   185  
   186  func (io StdIOConn) Write(b []byte) (n int, err error) {
   187  	return os.Stdout.Write(b)
   188  }
   189  
   190  func (io StdIOConn) Close() error {
   191  	return nil
   192  }
   193  
   194  func (io StdIOConn) LocalAddr() net.Addr {
   195  	return &net.UnixAddr{Name: "stdio", Net: "stdio"}
   196  }
   197  
   198  func (io StdIOConn) RemoteAddr() net.Addr {
   199  	return &net.UnixAddr{Name: "stdio", Net: "stdio"}
   200  }
   201  
   202  func (io StdIOConn) SetDeadline(t time.Time) error {
   203  	return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
   204  }
   205  
   206  func (io StdIOConn) SetReadDeadline(t time.Time) error {
   207  	return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
   208  }
   209  
   210  func (io StdIOConn) SetWriteDeadline(t time.Time) error {
   211  	return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
   212  }
   213  func DialStdIO(ctx context.Context) (*Client, error) {
   214  	return newClient(ctx, func(_ context.Context) (net.Conn, error) {
   215  		return StdIOConn{}, nil
   216  	})
   217  }
   218  
   219  func newClient(initctx context.Context, connectFunc func(context.Context) (net.Conn, error)) (*Client, error) {
   220  	conn, err := connectFunc(initctx)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	_, isHTTP := conn.(*httpConn)
   225  	c := &Client{
   226  		writeConn:   conn,
   227  		isHTTP:      isHTTP,
   228  		connectFunc: connectFunc,
   229  		close:       make(chan struct{}),
   230  		didQuit:     make(chan struct{}),
   231  		reconnected: make(chan net.Conn),
   232  		readErr:     make(chan error),
   233  		readResp:    make(chan []*jsonrpcMessage),
   234  		requestOp:   make(chan *requestOp),
   235  		sendDone:    make(chan error, 1),
   236  		respWait:    make(map[string]*requestOp),
   237  		subs:        make(map[string]*ClientSubscription),
   238  	}
   239  	if !isHTTP {
   240  		go c.dispatch(conn)
   241  	}
   242  	return c, nil
   243  }
   244  
   245  func (c *Client) nextID() json.RawMessage {
   246  	id := atomic.AddUint32(&c.idCounter, 1)
   247  	return []byte(strconv.FormatUint(uint64(id), 10))
   248  }
   249  
   250  //supportedmodules调用rpc_modules方法,检索
   251  //服务器上可用的API。
   252  func (c *Client) SupportedModules() (map[string]string, error) {
   253  	var result map[string]string
   254  	ctx, cancel := context.WithTimeout(context.Background(), subscribeTimeout)
   255  	defer cancel()
   256  	err := c.CallContext(ctx, &result, "rpc_modules")
   257  	return result, err
   258  }
   259  
   260  //CLOSE关闭客户机,中止任何飞行中的请求。
   261  func (c *Client) Close() {
   262  	if c.isHTTP {
   263  		return
   264  	}
   265  	select {
   266  	case c.close <- struct{}{}:
   267  		<-c.didQuit
   268  	case <-c.didQuit:
   269  	}
   270  }
   271  
   272  //调用使用给定的参数执行JSON-RPC调用,并将其解组为
   273  //如果没有发生错误,则返回结果。
   274  //
   275  //结果必须是一个指针,以便包JSON可以解组到其中。你
   276  //也可以传递nil,在这种情况下,结果将被忽略。
   277  func (c *Client) Call(result interface{}, method string, args ...interface{}) error {
   278  	ctx := context.Background()
   279  	return c.CallContext(ctx, result, method, args...)
   280  }
   281  
   282  //callContext使用给定的参数执行JSON-RPC调用。如果上下文是
   283  //在成功返回调用之前取消,callContext立即返回。
   284  //
   285  //结果必须是一个指针,以便包JSON可以解组到其中。你
   286  //也可以传递nil,在这种情况下,结果将被忽略。
   287  func (c *Client) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
   288  	msg, err := c.newMessage(method, args...)
   289  	if err != nil {
   290  		return err
   291  	}
   292  	op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}
   293  
   294  	if c.isHTTP {
   295  		err = c.sendHTTP(ctx, op, msg)
   296  	} else {
   297  		err = c.send(ctx, op, msg)
   298  	}
   299  	if err != nil {
   300  		return err
   301  	}
   302  
   303  //调度已接受请求,并将在退出时关闭通道。
   304  	switch resp, err := op.wait(ctx); {
   305  	case err != nil:
   306  		return err
   307  	case resp.Error != nil:
   308  		return resp.Error
   309  	case len(resp.Result) == 0:
   310  		return ErrNoResult
   311  	default:
   312  		return json.Unmarshal(resp.Result, &result)
   313  	}
   314  }
   315  
   316  //批处理调用将所有给定的请求作为单个批处理发送,并等待服务器
   317  //为所有人返回响应。
   318  //
   319  //与调用不同,批调用只返回I/O错误。任何特定于的错误
   320  //通过相应批处理元素的错误字段报告请求。
   321  //
   322  //注意,批处理调用不能在服务器端以原子方式执行。
   323  func (c *Client) BatchCall(b []BatchElem) error {
   324  	ctx := context.Background()
   325  	return c.BatchCallContext(ctx, b)
   326  }
   327  
   328  //批处理调用将所有给定的请求作为单个批处理发送,并等待服务器
   329  //为所有人返回响应。等待持续时间由
   330  //上下文的最后期限。
   331  //
   332  //与callContext不同,batchcallContext只返回已发生的错误
   333  //发送请求时。任何特定于请求的错误都会通过
   334  //对应批处理元素的错误字段。
   335  //
   336  //注意,批处理调用不能在服务器端以原子方式执行。
   337  func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
   338  	msgs := make([]*jsonrpcMessage, len(b))
   339  	op := &requestOp{
   340  		ids:  make([]json.RawMessage, len(b)),
   341  		resp: make(chan *jsonrpcMessage, len(b)),
   342  	}
   343  	for i, elem := range b {
   344  		msg, err := c.newMessage(elem.Method, elem.Args...)
   345  		if err != nil {
   346  			return err
   347  		}
   348  		msgs[i] = msg
   349  		op.ids[i] = msg.ID
   350  	}
   351  
   352  	var err error
   353  	if c.isHTTP {
   354  		err = c.sendBatchHTTP(ctx, op, msgs)
   355  	} else {
   356  		err = c.send(ctx, op, msgs)
   357  	}
   358  
   359  //等待所有响应返回。
   360  	for n := 0; n < len(b) && err == nil; n++ {
   361  		var resp *jsonrpcMessage
   362  		resp, err = op.wait(ctx)
   363  		if err != nil {
   364  			break
   365  		}
   366  //找到与此响应对应的元素。
   367  //由于调度,元素被保证存在
   368  //只向我们的频道发送有效的ID。
   369  		var elem *BatchElem
   370  		for i := range msgs {
   371  			if bytes.Equal(msgs[i].ID, resp.ID) {
   372  				elem = &b[i]
   373  				break
   374  			}
   375  		}
   376  		if resp.Error != nil {
   377  			elem.Error = resp.Error
   378  			continue
   379  		}
   380  		if len(resp.Result) == 0 {
   381  			elem.Error = ErrNoResult
   382  			continue
   383  		}
   384  		elem.Error = json.Unmarshal(resp.Result, elem.Result)
   385  	}
   386  	return err
   387  }
   388  
   389  //ethsubscribe在“eth”名称空间下注册一个订阅。
   390  func (c *Client) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error) {
   391  	return c.Subscribe(ctx, "eth", channel, args...)
   392  }
   393  
   394  //shhsubscribe在“shh”名称空间下注册一个订阅。
   395  func (c *Client) ShhSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error) {
   396  	return c.Subscribe(ctx, "shh", channel, args...)
   397  }
   398  
   399  //subscribe使用给定的参数调用“<namespace>\u subscribe”方法,
   400  //注册订阅。订阅的服务器通知为
   401  //发送到给定的频道。通道的元素类型必须与
   402  //订阅返回的内容类型应为。
   403  //
   404  //context参数取消设置订阅但没有的RPC请求
   405  //订阅返回后对订阅的影响。
   406  //
   407  //缓慢的订户最终将被删除。客户端缓冲区最多8000个通知
   408  //在考虑用户死亡之前。订阅错误通道将接收
   409  //errSubscriptionQueueOverflow。在通道上使用足够大的缓冲区或确保
   410  //通道通常至少有一个读卡器来防止这个问题。
   411  func (c *Client) Subscribe(ctx context.Context, namespace string, channel interface{}, args ...interface{}) (*ClientSubscription, error) {
   412  //首先检查通道类型。
   413  	chanVal := reflect.ValueOf(channel)
   414  	if chanVal.Kind() != reflect.Chan || chanVal.Type().ChanDir()&reflect.SendDir == 0 {
   415  		panic("first argument to Subscribe must be a writable channel")
   416  	}
   417  	if chanVal.IsNil() {
   418  		panic("channel given to Subscribe must not be nil")
   419  	}
   420  	if c.isHTTP {
   421  		return nil, ErrNotificationsUnsupported
   422  	}
   423  
   424  	msg, err := c.newMessage(namespace+subscribeMethodSuffix, args...)
   425  	if err != nil {
   426  		return nil, err
   427  	}
   428  	op := &requestOp{
   429  		ids:  []json.RawMessage{msg.ID},
   430  		resp: make(chan *jsonrpcMessage),
   431  		sub:  newClientSubscription(c, namespace, chanVal),
   432  	}
   433  
   434  //发送订阅请求。
   435  //响应的到达和有效性在Sub.Quit上发出信号。
   436  	if err := c.send(ctx, op, msg); err != nil {
   437  		return nil, err
   438  	}
   439  	if _, err := op.wait(ctx); err != nil {
   440  		return nil, err
   441  	}
   442  	return op.sub, nil
   443  }
   444  
   445  func (c *Client) newMessage(method string, paramsIn ...interface{}) (*jsonrpcMessage, error) {
   446  	params, err := json.Marshal(paramsIn)
   447  	if err != nil {
   448  		return nil, err
   449  	}
   450  	return &jsonrpcMessage{Version: "2.0", ID: c.nextID(), Method: method, Params: params}, nil
   451  }
   452  
   453  //发送寄存器op和调度循环,然后在连接上发送msg。
   454  //如果发送失败,则注销OP。
   455  func (c *Client) send(ctx context.Context, op *requestOp, msg interface{}) error {
   456  	select {
   457  	case c.requestOp <- op:
   458  		log.Trace("", "msg", log.Lazy{Fn: func() string {
   459  			return fmt.Sprint("sending ", msg)
   460  		}})
   461  		err := c.write(ctx, msg)
   462  		c.sendDone <- err
   463  		return err
   464  	case <-ctx.Done():
   465  //如果客户端过载或无法跟上,就会发生这种情况。
   466  //订阅通知。
   467  		return ctx.Err()
   468  	case <-c.didQuit:
   469  		return ErrClientQuit
   470  	}
   471  }
   472  
   473  func (c *Client) write(ctx context.Context, msg interface{}) error {
   474  	deadline, ok := ctx.Deadline()
   475  	if !ok {
   476  		deadline = time.Now().Add(defaultWriteTimeout)
   477  	}
   478  //上一次写入失败。尝试建立新连接。
   479  	if c.writeConn == nil {
   480  		if err := c.reconnect(ctx); err != nil {
   481  			return err
   482  		}
   483  	}
   484  	c.writeConn.SetWriteDeadline(deadline)
   485  	err := json.NewEncoder(c.writeConn).Encode(msg)
   486  	if err != nil {
   487  		c.writeConn = nil
   488  	}
   489  	return err
   490  }
   491  
   492  func (c *Client) reconnect(ctx context.Context) error {
   493  	newconn, err := c.connectFunc(ctx)
   494  	if err != nil {
   495  		log.Trace(fmt.Sprintf("reconnect failed: %v", err))
   496  		return err
   497  	}
   498  	select {
   499  	case c.reconnected <- newconn:
   500  		c.writeConn = newconn
   501  		return nil
   502  	case <-c.didQuit:
   503  		newconn.Close()
   504  		return ErrClientQuit
   505  	}
   506  }
   507  
   508  //调度是客户机的主循环。
   509  //它向等待调用和批调用发送读取消息
   510  //注册订阅的订阅通知。
   511  func (c *Client) dispatch(conn net.Conn) {
   512  //生成初始读取循环。
   513  	go c.read(conn)
   514  
   515  	var (
   516  lastOp        *requestOp    //跟踪上次发送操作
   517  requestOpLock = c.requestOp //保持发送锁时为零
   518  reading       = true        //如果为真,则运行读取循环
   519  	)
   520  	defer close(c.didQuit)
   521  	defer func() {
   522  		c.closeRequestOps(ErrClientQuit)
   523  		conn.Close()
   524  		if reading {
   525  //清空读取通道,直到读取结束。
   526  			for {
   527  				select {
   528  				case <-c.readResp:
   529  				case <-c.readErr:
   530  					return
   531  				}
   532  			}
   533  		}
   534  	}()
   535  
   536  	for {
   537  		select {
   538  		case <-c.close:
   539  			return
   540  
   541  //读取路径。
   542  		case batch := <-c.readResp:
   543  			for _, msg := range batch {
   544  				switch {
   545  				case msg.isNotification():
   546  					log.Trace("", "msg", log.Lazy{Fn: func() string {
   547  						return fmt.Sprint("<-readResp: notification ", msg)
   548  					}})
   549  					c.handleNotification(msg)
   550  				case msg.isResponse():
   551  					log.Trace("", "msg", log.Lazy{Fn: func() string {
   552  						return fmt.Sprint("<-readResp: response ", msg)
   553  					}})
   554  					c.handleResponse(msg)
   555  				default:
   556  					log.Debug("", "msg", log.Lazy{Fn: func() string {
   557  						return fmt.Sprint("<-readResp: dropping weird message", msg)
   558  					}})
   559  //托多:也许接近
   560  				}
   561  			}
   562  
   563  		case err := <-c.readErr:
   564  			log.Debug("<-readErr", "err", err)
   565  			c.closeRequestOps(err)
   566  			conn.Close()
   567  			reading = false
   568  
   569  		case newconn := <-c.reconnected:
   570  			log.Debug("<-reconnected", "reading", reading, "remote", conn.RemoteAddr())
   571  			if reading {
   572  //等待上一个读取循环退出。这是一个罕见的病例。
   573  				conn.Close()
   574  				<-c.readErr
   575  			}
   576  			go c.read(newconn)
   577  			reading = true
   578  			conn = newconn
   579  
   580  //发送路径。
   581  		case op := <-requestOpLock:
   582  //停止侦听进一步的发送操作,直到当前操作完成。
   583  			requestOpLock = nil
   584  			lastOp = op
   585  			for _, id := range op.ids {
   586  				c.respWait[string(id)] = op
   587  			}
   588  
   589  		case err := <-c.sendDone:
   590  			if err != nil {
   591  //删除上次发送的响应处理程序。我们把它们移到这里
   592  //因为错误已经在call或batchcall中处理。当
   593  //读取循环停止,它将发出所有其他当前操作的信号。
   594  				for _, id := range lastOp.ids {
   595  					delete(c.respWait, string(id))
   596  				}
   597  			}
   598  //再次收听发送操作。
   599  			requestOpLock = c.requestOp
   600  			lastOp = nil
   601  		}
   602  	}
   603  }
   604  
   605  //closerequestops取消阻止挂起的发送操作和活动订阅。
   606  func (c *Client) closeRequestOps(err error) {
   607  	didClose := make(map[*requestOp]bool)
   608  
   609  	for id, op := range c.respWait {
   610  //删除op,以便以后的调用不会再次关闭op.resp。
   611  		delete(c.respWait, id)
   612  
   613  		if !didClose[op] {
   614  			op.err = err
   615  			close(op.resp)
   616  			didClose[op] = true
   617  		}
   618  	}
   619  	for id, sub := range c.subs {
   620  		delete(c.subs, id)
   621  		sub.quitWithError(err, false)
   622  	}
   623  }
   624  
   625  func (c *Client) handleNotification(msg *jsonrpcMessage) {
   626  	if !strings.HasSuffix(msg.Method, notificationMethodSuffix) {
   627  		log.Debug("dropping non-subscription message", "msg", msg)
   628  		return
   629  	}
   630  	var subResult struct {
   631  		ID     string          `json:"subscription"`
   632  		Result json.RawMessage `json:"result"`
   633  	}
   634  	if err := json.Unmarshal(msg.Params, &subResult); err != nil {
   635  		log.Debug("dropping invalid subscription message", "msg", msg)
   636  		return
   637  	}
   638  	if c.subs[subResult.ID] != nil {
   639  		c.subs[subResult.ID].deliver(subResult.Result)
   640  	}
   641  }
   642  
   643  func (c *Client) handleResponse(msg *jsonrpcMessage) {
   644  	op := c.respWait[string(msg.ID)]
   645  	if op == nil {
   646  		log.Debug("unsolicited response", "msg", msg)
   647  		return
   648  	}
   649  	delete(c.respWait, string(msg.ID))
   650  //对于正常响应,只需将响应转发到call/batchcall。
   651  	if op.sub == nil {
   652  		op.resp <- msg
   653  		return
   654  	}
   655  //对于订阅响应,如果服务器
   656  //表示成功。ethsubscribe在任何情况下都可以通过
   657  //Op.Resp频道。
   658  	defer close(op.resp)
   659  	if msg.Error != nil {
   660  		op.err = msg.Error
   661  		return
   662  	}
   663  	if op.err = json.Unmarshal(msg.Result, &op.sub.subid); op.err == nil {
   664  		go op.sub.start()
   665  		c.subs[op.sub.subid] = op.sub
   666  	}
   667  }
   668  
   669  //阅读发生在一个专门的Goroutine上。
   670  
   671  func (c *Client) read(conn net.Conn) error {
   672  	var (
   673  		buf json.RawMessage
   674  		dec = json.NewDecoder(conn)
   675  	)
   676  	readMessage := func() (rs []*jsonrpcMessage, err error) {
   677  		buf = buf[:0]
   678  		if err = dec.Decode(&buf); err != nil {
   679  			return nil, err
   680  		}
   681  		if isBatch(buf) {
   682  			err = json.Unmarshal(buf, &rs)
   683  		} else {
   684  			rs = make([]*jsonrpcMessage, 1)
   685  			err = json.Unmarshal(buf, &rs[0])
   686  		}
   687  		return rs, err
   688  	}
   689  
   690  	for {
   691  		resp, err := readMessage()
   692  		if err != nil {
   693  			c.readErr <- err
   694  			return err
   695  		}
   696  		c.readResp <- resp
   697  	}
   698  }
   699  
   700  //订阅。
   701  
   702  //客户端订阅表示通过ethsubscribe建立的订阅。
   703  type ClientSubscription struct {
   704  	client    *Client
   705  	etype     reflect.Type
   706  	channel   reflect.Value
   707  	namespace string
   708  	subid     string
   709  	in        chan json.RawMessage
   710  
   711  quitOnce sync.Once     //确保退出关闭一次
   712  quit     chan struct{} //退出订阅时将关闭Quit
   713  errOnce  sync.Once     //确保err关闭一次
   714  	err      chan error
   715  }
   716  
   717  func newClientSubscription(c *Client, namespace string, channel reflect.Value) *ClientSubscription {
   718  	sub := &ClientSubscription{
   719  		client:    c,
   720  		namespace: namespace,
   721  		etype:     channel.Type().Elem(),
   722  		channel:   channel,
   723  		quit:      make(chan struct{}),
   724  		err:       make(chan error, 1),
   725  		in:        make(chan json.RawMessage),
   726  	}
   727  	return sub
   728  }
   729  
   730  //err返回订阅错误通道。err的预期用途是
   731  //客户端连接意外关闭时重新订阅。
   732  //
   733  //当订阅到期时,错误通道接收到一个值。
   734  //出错。如果调用了close,则接收到的错误为nil。
   735  //在基础客户端上,没有发生其他错误。
   736  //
   737  //当对订阅调用Unsubscribe时,错误通道将关闭。
   738  func (sub *ClientSubscription) Err() <-chan error {
   739  	return sub.err
   740  }
   741  
   742  //取消订阅取消订阅通知并关闭错误通道。
   743  //它可以安全地被多次调用。
   744  func (sub *ClientSubscription) Unsubscribe() {
   745  	sub.quitWithError(nil, true)
   746  	sub.errOnce.Do(func() { close(sub.err) })
   747  }
   748  
   749  func (sub *ClientSubscription) quitWithError(err error, unsubscribeServer bool) {
   750  	sub.quitOnce.Do(func() {
   751  //调度循环将无法执行取消订阅调用
   752  //如果交货时受阻。关闭Sub.Quit First,因为它
   753  //解除锁定传递。
   754  		close(sub.quit)
   755  		if unsubscribeServer {
   756  			sub.requestUnsubscribe()
   757  		}
   758  		if err != nil {
   759  			if err == ErrClientQuit {
   760  err = nil //遵循订阅语义。
   761  			}
   762  			sub.err <- err
   763  		}
   764  	})
   765  }
   766  
   767  func (sub *ClientSubscription) deliver(result json.RawMessage) (ok bool) {
   768  	select {
   769  	case sub.in <- result:
   770  		return true
   771  	case <-sub.quit:
   772  		return false
   773  	}
   774  }
   775  
   776  func (sub *ClientSubscription) start() {
   777  	sub.quitWithError(sub.forward())
   778  }
   779  
   780  func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) {
   781  	cases := []reflect.SelectCase{
   782  		{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.quit)},
   783  		{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.in)},
   784  		{Dir: reflect.SelectSend, Chan: sub.channel},
   785  	}
   786  	buffer := list.New()
   787  	defer buffer.Init()
   788  	for {
   789  		var chosen int
   790  		var recv reflect.Value
   791  		if buffer.Len() == 0 {
   792  //空闲,省略发送案例。
   793  			chosen, recv, _ = reflect.Select(cases[:2])
   794  		} else {
   795  //非空缓冲区,发送第一个排队的项目。
   796  			cases[2].Send = reflect.ValueOf(buffer.Front().Value)
   797  			chosen, recv, _ = reflect.Select(cases)
   798  		}
   799  
   800  		switch chosen {
   801  case 0: //<退出
   802  			return nil, false
   803  case 1: //<-in in
   804  			val, err := sub.unmarshal(recv.Interface().(json.RawMessage))
   805  			if err != nil {
   806  				return err, true
   807  			}
   808  			if buffer.Len() == maxClientSubscriptionBuffer {
   809  				return ErrSubscriptionQueueOverflow, true
   810  			}
   811  			buffer.PushBack(val)
   812  case 2: //子通道<
   813  cases[2].Send = reflect.Value{} //不要抓住价值。
   814  			buffer.Remove(buffer.Front())
   815  		}
   816  	}
   817  }
   818  
   819  func (sub *ClientSubscription) unmarshal(result json.RawMessage) (interface{}, error) {
   820  	val := reflect.New(sub.etype)
   821  	err := json.Unmarshal(result, val.Interface())
   822  	return val.Elem().Interface(), err
   823  }
   824  
   825  func (sub *ClientSubscription) requestUnsubscribe() error {
   826  	var result interface{}
   827  	return sub.client.Call(&result, sub.namespace+unsubscribeMethodSuffix, sub.subid)
   828  }
   829