Documentation ¶
Overview ¶
Package serialclient provides a client for synchronous client-server communication.
This work is licensed under CC0 1.0 Universal (CC0 1.0), Public Domain Dedication. For details see:
http://creativecommons.org/publicdomain/zero/1.0/
Online go-documentation is available at:
https://godoc.org/bitbucket.org/pcas/serverutil/serial/serialclient
The basic communication protocol is described in package bitbucket.org/pcas/serverutil/serial (https://godoc.org/bitbucket.org/pcas/serverutil/serial). In summary:
client sends a task code specifying the task for the server to perform;
client sends message data (implementation specific, encoded as described in https://godoc.org/bitbucket.org/pcas/serverutil/serial);
server sends a response code, which one of - serverutil.OK - serverutil.Error - serverutil.Goodbye
4a. if the response code is serverutil.OK, server sends response data (implementation-specific, encoded as described in https://godoc.org/bitbucket.org/pcas/serverutil/serial);
4b. if the response code is serverutil.Error, server sends a serverutil.ErrorCode describing the error;
4c. if the response code is serverutil.Googbye then the server is closing the connection without handling the task.
The server is free to silently close the connection at any time.
To establish a connection to the server, do something like:
// Dial the serial server conn, err := net.Dial("tcp", "hostname:port") if err != nil { // Handle the error // ... } // Make the connection into a serial client sc := serialclient.New(conn, binary.BigEndian, &serverutil.Timeout{ Wait: 3 * time.Minute, Read: 5 * time.Second, Write: 5 * time.Second, KeepAlive: 1 * time.Minute, }) defer sc.Close()
Here Wait, Read, and Write are, respectively, the time.Duration timeout to use whilst waiting for a response from the server, the rolling read timeout once a response has started, and the rolling write timeout. KeepAlive is the frequency of the keep-alive ping that the client will send to the server to keep the connection alive. A KeepAlive frequency of 0 will disable the keep-alive ping.
To send a task code and message data to the server (that is, to do steps 1 and 2 above), do:
// Prepare an io.Reader r that will provide the message data (if any). // The contents of r will automatically be encoded before sending to // the server; you are not responsible for encoding. // ... // Send the task code and message data resp, err := sc.Send(taskCode, r) if err != nil { // Handle the error // ... } defer resp.Close()
If sc.Send fails -- that is, if err is non-nil -- something has gone wrong and the connection to the server will need to be rebuild. The error serialclient.ErrConnectionClosed indicates that the server has gone away gracefully.
A successful call to sc.Send returns a *Response object resp containing the response from the server. The response satisfies the io.ReadCloser and binaryutil.BinaryReader interfaces. It is essential that you call resp.Close() on the response once finished with it: subsequent calls to sc.Send will block until the response has been closed.
If the server sent a serverutil.OK response in step 3, then resp.IsOK() will return true and the response data (if any) sent by the sever can be read from resp. Any response data will be automatically decoded; you are not responsible for decoding. If the server sent a serverutil.Error response in step 3, then resp.IsError() will return true, e where e is the error code describing the error. A serverutil.Goodbye response code is handled by the Send method; in this case Send will return an serialclient.ErrConnectionClosed error.
See package bitbucket.org/pcas/logger (https://godoc.org/bitbucket.org/pcas/logger) for a real-world example of a client that uses the serialclient package.
Index ¶
- type Interface
- type Response
- func (r *Response) ByteOrder() binary.ByteOrder
- func (r *Response) Close() error
- func (r *Response) IsError() (bool, serverutil.ErrorCode)
- func (r *Response) IsOK() bool
- func (r *Response) Read(p []byte) (int, error)
- func (r *Response) ReadByte() (byte, error)
- func (r *Response) ReadInt16() (int16, error)
- func (r *Response) ReadInt32() (int32, error)
- func (r *Response) ReadInt64() (int64, error)
- func (r *Response) ReadInt8() (int8, error)
- func (r *Response) ReadUint16() (uint16, error)
- func (r *Response) ReadUint32() (uint32, error)
- func (r *Response) ReadUint64() (uint64, error)
- func (r *Response) ReadUint8() (uint8, error)
- type Server
- func (sc *Server) ByteOrder() binary.ByteOrder
- func (sc *Server) Close() (err error)
- func (sc *Server) Disconnect(d time.Duration)
- func (sc *Server) LocalAddr() net.Addr
- func (sc *Server) Log() log.Interface
- func (sc *Server) Metadata() *serial.TaskMetadata
- func (sc *Server) Metrics() metrics.Interface
- func (sc *Server) RemoteAddr() net.Addr
- func (sc *Server) Send(t serverutil.TaskCode, r io.Reader) (*Response, error)
- func (sc *Server) SetLogger(l log.Interface)
- func (sc *Server) SetMetrics(m metrics.Interface)
- func (sc *Server) TaskCodes() []serverutil.TaskCode
- func (sc *Server) Timestamp() time.Time
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Interface ¶
type Interface interface { binaryutil.ByteOrderer Send(t serverutil.TaskCode, r io.Reader) (*Response, error) }
Interface is the minimum interface required to send a message.
type Response ¶
type Response struct {
// contains filtered or unexported fields
}
Response describes the task response header read from the server. The Timestamp is the time this response was received. The response Code will be one of serverutil.OK or serverutil.Error. If the response Code is serverutil.Error then Error will be set to the corresponding error code; for any other response Code, the value of Error is meaningless and should be ignored.
func (*Response) IsError ¶
func (r *Response) IsError() (bool, serverutil.ErrorCode)
IsError returns true if and only if the response code sent by the server is serverutil.Error. If true, also returns the error code.
func (*Response) IsOK ¶
IsOK returns true if and only if the response code sent by the server is serverutil.OK.
func (*Response) ReadUint16 ¶
ReadUint16 reads a uint16.
func (*Response) ReadUint32 ¶
ReadUint32 reads a uint32.
func (*Response) ReadUint64 ¶
ReadUint64 reads a uint64.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server represents a client's connection to the server.
func New ¶
New creates a new server connection using the given connection conn, byte order e, and timeout values. If timeout is nil then the default timeout durations will be used.
func (*Server) Disconnect ¶
Disconnect begins a graceful disconnection, preventing new tasks from running, and scheduling a future Close on the connection after duration d has elapsed. Note that there is no way to cancel a graceful disconnection once started. If Disconnect is called again, then the final Close will be performed after the shortest of the two durations has expired. This is a non-blocking method.
func (*Server) Metadata ¶
func (sc *Server) Metadata() *serial.TaskMetadata
Metadata returns the metadata for the current task, or nil if no task is currently assigned.
func (*Server) RemoteAddr ¶
RemoteAddr returns the remote network address.
func (*Server) Send ¶
Send submits the indicated task, with message data read from r, to the server. On success the response will be returned. Any response data from the server can be read from the returned response. If no message data needs to be sent, it is permitted for r to be nil. It is the user's responsibility to ensure that the Close method is called on this response; subsequent calls to Send will block until the response has been closed.
func (*Server) SetMetrics ¶
SetMetrics sets a metrics endpoint.
func (*Server) TaskCodes ¶
func (sc *Server) TaskCodes() []serverutil.TaskCode
TaskCodes returns a slice of all assigned tasks codes.