memconn

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 1, 2018 License: Apache-2.0 Imports: 7 Imported by: 18

README

MemConn GoDoc Build Status Go Report Card

MemConn provides named, in-memory network connections for Go.

Create a Server

A new net.Listener used to serve HTTP, gRPC, etc. is created with memconn.Listen:

lis, err := memconn.Listen("memu", "UniqueName")

Creating a Client (Dial)

Clients can dial any named connection:

client, err := memconn.Dial("memu", "UniqueName")

Network Types

MemCon supports the following network types:

Network Description
memb A buffered, in-memory implementation of net.Conn
memu An unbuffered, in-memory implementation of net.Conn

Performance

The benchmark results illustrate MemConn's performance versus TCP and UNIX domain sockets:

ops ns/op B/op allocs/op

MemConn is more performant than TCP and UNIX domain sockets with respect to the CPU. While MemConn does allocate more memory, this is to be expected since MemConn is an in-memory implementation of the net.Conn interface.

Documentation

Overview

Example (Http)

Example_http illustrates how to create an HTTP server and client using memconn.

package main

import (
	"context"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"

	"github.com/akutz/memconn"
)

func main() {

	// Create a new, named listener using the in-memory, unbuffered
	// network "memu" and address "MyNamedNetwork".
	lis, err := memconn.Listen("memu", "MyNamedNetwork")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	// Create a new HTTP mux and register a handler with it that responds
	// to requests with the text "Hello, world.".
	mux := http.NewServeMux()
	mux.Handle("/", http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			fmt.Fprint(w, "Hello, world.")
		}))

	// Start an HTTP server using the HTTP mux.
	go func() {
		if err := http.Serve(lis, mux); err != http.ErrServerClosed {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}()

	// Create a new HTTP client that delegates its dialing to memconn.
	client := &http.Client{
		Transport: &http.Transport{
			DialContext: func(
				ctx context.Context, _, _ string) (net.Conn, error) {
				return memconn.DialContext(ctx, "memu", "MyNamedNetwork")
			},
		},
	}

	// Get the root resource and copy its response to os.Stdout. Please
	// note that the URL must contain a host name, even if it's ignored.
	rep, err := client.Get("http://host/")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer rep.Body.Close()
	if _, err := io.Copy(os.Stdout, rep.Body); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

}
Output:

Hello, world.
Example (Http_mapped_network)

Example_http_mapped_network illustrates how to create an HTTP server and client with the "tcp" network mapped to "memu" to make creating an HTTP client easier.

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"

	"github.com/akutz/memconn"
)

func main() {

	// MemConn's MapNetwork function enables mapping known network
	// types to different types. This is useful for when using MemConn
	// with Golang's "http" package since the "http.Client" builds
	// the network address from the provided resource URL. Please
	// see the next comment for more information.
	memconn.MapNetwork("tcp", "memu")

	// Create a new, named listener using the in-memory, unbuffered
	// network "memu".
	//
	// Please note that the listener's address is "host:80". While
	// MemConn names do not need to be unique and are free-form, this
	// name was selected due to the way the "http.Client" builds the
	// network address from the provided resource URL.
	//
	// For example, if the request is "GET http://host/" then the HTTP
	// client dials "network=tcp, address=host:80". In combination
	// with the above "MapNetwork" function this means creating
	// a MemConn listener with the address "host:80" requires no special
	// address translation is required for the when using
	// "memconn.DialContext" with the HTTP client transport.
	lis, err := memconn.Listen("memu", "host:80")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	// Create a new HTTP mux and register a handler with it that responds
	// to requests with the text "Hello, world.".
	mux := http.NewServeMux()
	mux.Handle("/", http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			fmt.Fprint(w, "Hello, world.")
		}))

	// Start an HTTP server using the HTTP mux.
	go func() {
		if err := http.Serve(lis, mux); err != http.ErrServerClosed {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}()

	// Create a new HTTP client that delegates its dialing to memconn.
	client := &http.Client{
		Transport: &http.Transport{DialContext: memconn.DialContext},
	}

	// Get the root resource and copy its response to os.Stdout. The
	// absence of a port means the address sent to the HTTP client's
	// dialer will be "host:80".
	rep, err := client.Get("http://host/")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer rep.Body.Close()
	if _, err := io.Copy(os.Stdout, rep.Body); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

}
Output:

Hello, world.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Dial

func Dial(network, address string) (net.Conn, error)

Dial dials a named connection.

Known networks are "memb" (memconn buffered) and "memu" (memconn unbuffered).

When the provided network is unknown the operation defers to net.Dial.

func DialContext

func DialContext(
	ctx context.Context,
	network, address string) (net.Conn, error)

DialContext dials a named connection using a Go context to provide timeout behavior.

Please see Dial for more information.

func Listen

func Listen(network, address string) (net.Listener, error)

Listen begins listening at address for the specified network.

Known networks are "memb" (memconn buffered) and "memu" (memconn unbuffered).

When the specified address is already in use on the specified network an error is returned.

When the provided network is unknown the operation defers to net.Dial.

func MapNetwork

func MapNetwork(from, to string)

MapNetwork enables mapping the network value provided to this Provider's Dial and Listen functions from the specified "from" value to the specified "to" value.

For example, calling MapNetwork("tcp", "memu") means a subsequent Dial("tcp", "address") gets translated to Dial("memu", "address").

Calling MapNetwork("tcp", "") removes any previous translation for the "tcp" network.

func Pipe

func Pipe() (net.Conn, net.Conn)

Pipe creates a synchronous, in-memory, full duplex network connection; both ends implement the Conn interface. Reads on one end are matched with writes on the other, copying data directly between the two; there is no internal buffering.

Types

type Addr

type Addr struct {
	// Name is the name of the endpoint.
	Name string
	// contains filtered or unexported fields
}

Addr represents the address of an in-memory endpoint.

func (Addr) Buffered

func (a Addr) Buffered() bool

Buffered indicates whether or not the address refers to a buffered network type.

func (Addr) Network

func (a Addr) Network() string

Network returns the address's network.

func (Addr) String

func (a Addr) String() string

String returns the address's name.

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is an in-memory implementation of Golang's "net.Conn" interface.

func DialMem

func DialMem(network string, laddr, raddr *Addr) (*Conn, error)

DialMem dials a named connection.

Known networks are "memb" (memconn buffered) and "memu" (memconn unbuffered).

If laddr is nil then a new address is generated using time.Now().UnixNano(). Please note that client addresses are not required to be unique.

If raddr is nil then the "localhost" endpoint is used on the specified network.

func DialMemContext

func DialMemContext(
	ctx context.Context,
	network string,
	laddr, raddr *Addr) (*Conn, error)

DialMemContext dials a named connection using a Go context to provide timeout behavior.

Please see DialMem for more information.

func (*Conn) BufferSize

func (c *Conn) BufferSize() uint64

BufferSize gets the number of bytes allowed to be queued for asynchrnous Write operations.

Please note that this function will always return zero for unbuffered connections.

Please see the function SetBufferSize for more information.

func (*Conn) Close

func (c *Conn) Close() error

Close implements the net.Conn Close method.

func (*Conn) CloseTimeout

func (c *Conn) CloseTimeout() time.Duration

CloseTimeout gets the time.Duration value used when closing buffered connections.

Please note that this function will always return zero for unbuffered connections.

Please see the function SetCloseTimeout for more information.

func (*Conn) CopyOnWrite

func (c *Conn) CopyOnWrite() bool

CopyOnWrite gets a flag indicating whether or not copy-on-write is enabled for this connection.

Please note that this function will always return false for unbuffered connections.

Please see the function SetCopyOnWrite for more information.

func (*Conn) Errs

func (c *Conn) Errs() <-chan error

Errs returns a channel that receives errors that may occur as the result of buffered write operations.

This function will always return nil for unbuffered connections.

Please note that the channel returned by this function is not closed when the connection is closed. This is because errors may continue to be sent over this channel as the result of asynchronous writes occurring after the connection is closed. Therefore this channel should not be used to determine when the connection is closed.

func (*Conn) LocalAddr

func (c *Conn) LocalAddr() net.Addr

LocalAddr implements the net.Conn LocalAddr method.

func (*Conn) LocalBuffered

func (c *Conn) LocalBuffered() bool

LocalBuffered returns a flag indicating whether or not the local side of the connection is buffered.

func (*Conn) Read

func (c *Conn) Read(b []byte) (int, error)

Read implements the net.Conn Read method.

func (*Conn) RemoteAddr

func (c *Conn) RemoteAddr() net.Addr

RemoteAddr implements the net.Conn RemoteAddr method.

func (*Conn) RemoteBuffered

func (c *Conn) RemoteBuffered() bool

RemoteBuffered returns a flag indicating whether or not the remote side of the connection is buffered.

func (*Conn) SetBufferSize

func (c *Conn) SetBufferSize(i uint64)

SetBufferSize sets the number of bytes allowed to be queued for asynchronous Write operations. Once the amount of data pending a Write operation exceeds the specified size, subsequent Writes will block until the queued data no longer exceeds the allowed ceiling.

A value of zero means no maximum is defined.

If a Write operation's payload length exceeds the buffer size (except for zero) then the Write operation is handled synchronously.

Please note that setting the buffer size has no effect on unbuffered connections.

func (*Conn) SetCloseTimeout

func (c *Conn) SetCloseTimeout(duration time.Duration)

SetCloseTimeout sets a time.Duration value used by the Close function to determine the amount of time to wait for pending, buffered Writes to complete before closing the connection.

The default timeout value is 10 seconds. A zero value does not mean there is no timeout, rather it means the timeout is immediate.

Please note that setting this value has no effect on unbuffered connections.

func (*Conn) SetCopyOnWrite

func (c *Conn) SetCopyOnWrite(enabled bool)

SetCopyOnWrite sets a flag indicating whether or not copy-on-write is enabled for this connection.

When a connection is buffered, data submitted to a Write operation is processed in a goroutine and the function returns control to the caller immediately. Because of this, it's possible to modify the data provided to the Write function before or during the actual Write operation. Enabling copy-on-write causes the payload to be copied to a new buffer before control is returned to the caller.

Please note that enabling copy-on-write will double the amount of memory required for all Write operations.

Please note that enabling copy-on-write has no effect on unbuffered connections.

func (*Conn) SetDeadline

func (p *Conn) SetDeadline(t time.Time) error

func (*Conn) SetReadDeadline

func (c *Conn) SetReadDeadline(t time.Time) error

SetReadDeadline implements the net.Conn SetReadDeadline method.

func (*Conn) SetWriteDeadline

func (c *Conn) SetWriteDeadline(t time.Time) error

SetWriteDeadline implements the net.Conn SetWriteDeadline method.

func (*Conn) Write

func (c *Conn) Write(b []byte) (int, error)

Write implements the net.Conn Write method.

type Listener

type Listener struct {
	// contains filtered or unexported fields
}

Listener implements the net.Listener interface.

func ListenMem

func ListenMem(network string, laddr *Addr) (*Listener, error)

ListenMem begins listening at laddr.

Known networks are "memb" (memconn buffered) and "memu" (memconn unbuffered).

If laddr is nil then ListenMem listens on "localhost" on the specified network.

func (*Listener) Accept

func (l *Listener) Accept() (net.Conn, error)

Accept implements the net.Listener Accept method.

func (*Listener) AcceptMemConn

func (l *Listener) AcceptMemConn() (*Conn, error)

AcceptMemConn implements the net.Listener Accept method logic and returns a *memconn.Conn object.

func (*Listener) Addr

func (l *Listener) Addr() net.Addr

Addr implements the net.Listener Addr method.

func (*Listener) Close

func (l *Listener) Close() error

Close implements the net.Listener Close method.

type Provider

type Provider struct {
	// contains filtered or unexported fields
}

Provider is used to track named MemConn objects.

func (*Provider) Dial

func (p *Provider) Dial(network, address string) (net.Conn, error)

Dial dials a named connection.

Known networks are "memb" (memconn buffered) and "memu" (memconn unbuffered).

When the provided network is unknown the operation defers to net.Dial.

func (*Provider) DialContext

func (p *Provider) DialContext(
	ctx context.Context,
	network, address string) (net.Conn, error)

DialContext dials a named connection using a Go context to provide timeout behavior.

Please see Dial for more information.

func (*Provider) DialMem

func (p *Provider) DialMem(
	network string, laddr, raddr *Addr) (*Conn, error)

DialMem dials a named connection.

Known networks are "memb" (memconn buffered) and "memu" (memconn unbuffered).

If laddr is nil then a new address is generated using time.Now().UnixNano(). Please note that client addresses are not required to be unique.

If raddr is nil then the "localhost" endpoint is used on the specified network.

func (*Provider) DialMemContext

func (p *Provider) DialMemContext(
	ctx context.Context,
	network string,
	laddr, raddr *Addr) (*Conn, error)

DialMemContext dials a named connection using a Go context to provide timeout behavior.

Please see DialMem for more information.

func (*Provider) Listen

func (p *Provider) Listen(network, address string) (net.Listener, error)

Listen begins listening at address for the specified network.

Known networks are "memb" (memconn buffered) and "memu" (memconn unbuffered).

When the specified address is already in use on the specified network an error is returned.

When the provided network is unknown the operation defers to net.Dial.

func (*Provider) ListenMem

func (p *Provider) ListenMem(network string, laddr *Addr) (*Listener, error)

ListenMem begins listening at laddr.

Known networks are "memb" (memconn buffered) and "memu" (memconn unbuffered).

If laddr is nil then ListenMem listens on "localhost" on the specified network.

func (*Provider) MapNetwork

func (p *Provider) MapNetwork(from, to string)

MapNetwork enables mapping the network value provided to this Provider's Dial and Listen functions from the specified "from" value to the specified "to" value.

For example, calling MapNetwork("tcp", "memu") means a subsequent Dial("tcp", "address") gets translated to Dial("memu", "address").

Calling MapNetwork("tcp", "") removes any previous translation for the "tcp" network.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL