Skip to content

A simple, fast approach to implement your communication protocol.

License

Notifications You must be signed in to change notification settings

hedzr/go-socketlib

Repository files navigation

go-socketlib

Go GitHub go.mod Go version GitHub tag (latest SemVer) Go Dev GoDoc Go Report Card

go-socketlib provides a simple, fast approach to implement your communication protocol.

Features

  • supports TCP, UDP, and Unix socket server/client developing
  • Wrap the dirty jobs in programming socket server and client so that you can devote into protocol design and coding.
  • Write your business logical with api.Interceptor and api.UdpInterceptor, also [api.ServerInterceptor] and [api.ServerUDPInterceptor].

History

For full list, have a see at CHANGELOG.

  • v1.1.0

    • upgrade deps and security patches
    • improved logger to compliant with hedzr/logg/slog and log/slog
    • go 1.22.7 needed
  • v1.0.x

    • [BREAK] Rewritten with new API.
    • go 1.21+ needed
    • v1.0.1: pre-released for primary structure frozen now.
  • v0.5.x

    • Old archive here.

Getting Start

Import

import "github.com/hedzr/go-socketlib"

Write a TCP server

go-socketlib has been integrated with cmdr. Here is a full app:

package main

import (
	"github.com/hedzr/cmdr"
	"github.com/hedzr/go-socketlib/tcp/client"
	"github.com/hedzr/go-socketlib/tcp/server"
	"github.com/hedzr/log"
	"github.com/hedzr/logex/build"
)

func main() {
	if err := cmdr.Exec(buildRootCmd(),
		cmdr.WithLogx(build.New(log.NewLoggerConfigWith(true, "sugar", "debug"))),
		//cmdr.WithUnknownOptionHandler(onUnknownOptionHandler),
		//cmdr.WithUnhandledErrorHandler(onUnhandledErrorHandler),
	); err != nil {
		cmdr.Logger.Fatalf("error: %+v", err)
	}
}

func buildRootCmd() (rootCmd *cmdr.RootCommand) {
	root := cmdr.Root(appName, "1.0.1").
		Header("fluent - test for cmdr - no version - hedzr").
		Description(desc, longDesc).
		Examples(examples)
	rootCmd = root.RootCommand()

	socketlibCmd(root)
	return
}

func socketlibCmd(root cmdr.OptCmd) {
	// for TCP server/client
  
	aCmd := root.NewSubCommand("tcp", "tcp", "socket", "socketlib").
		Description("go-socketlib operations...", "").
		Group("TCP")
	server.AttachToCmdr(aCmd, server.WithPort(1983))
	client.AttachToCmdr(aCmd, client.WithCmdrPort(1983))
  
	// for UDP server/client
  
	udpCmd := root.NewSubCommand("udp", "udp").
		Description("go-socketlib UDP operations...", "").
		Group("UDP")

	server.AttachToCmdr(udpCmd, server.WithCmdrUDPMode(true), server.WithCmdrPort(1984))
	client.AttachToCmdr(udpCmd, client.WithCmdrUDPMode(true), client.WithCmdrPort(1984))
}

const (
	appName   = "tcp-tool"
	copyright = "tcp-tool is an effective devops tool"
	desc      = "tcp-tool is an effective devops tool. It make an demo application for `cmdr`."
	longDesc  = "tcp-tool is an effective devops tool. It make an demo application for `cmdr`."
	examples  = `
$ {{.AppName}} --help
  show help screen.
`
)

Run it:

$ go run ./cli tcp --help
tcp-tool is an effective devops tool by hedzr - v1.0.1

Usages:
    tcp-tool tcp [Sub-Commands] [tail args...] [Options] [Parent/Global Options]

Description:
    go-socketlib TCO operations...

Sub-Commands:
  c, client                                       TCP/UDP/Unix client operations
  s, server                                       TCP/UDP/Unix Server Operations

Global Options:
  [Misc]
          --config=[Locations of config files]    load config files from where you specified (default [Locations of config files]=)
  -q,     --quiet                                 No more screen output. [env: QUITE] (default=false)
  -trace, --trace,--tr                            enable trace mode for tcp/mqtt send/recv data dump [env: TRACE] (default=false)
  -v,     --verbose                               Show this help screen [env: VERBOSE] (default=false)

Type '-h'/'-?' or '--help' to get command help screen.
More: '-D'/'--debug'['--env'|'--raw'|'--more'], '-V'/'--version', '-#'/'--build-info', '--no-color', '--strict-mode', '--no-env-overrides'...

The server options:

❯ go run ./cli tcp server --help
tcp-tool is an effective devops tool by hedzr - v1.0.1

Usages:
    tcp-tool tcp server [tail args...] [Options] [Parent/Global Options]

Description:
    TCP/UDP/Unix Server Operations

Options:
     --network                                    network: tcp, tcp4, tcp6, unix, unixpacket, and udp, udp4, udp6 (default='tcp')
  [TCP/UDP]
  -a, --addr=HOST-or-IP,--adr,--address           The address to listen to (default HOST-or-IP=)
  -p, --port=PORT                                 The port to listen on (default PORT=1983)
  [TLS]
  -tls, --enable-tls                              enable TLS mode (default=false)
  -ca,  --cacert=PATH,--ca-cert                   CA cert path (.cer,.crt,.pem) if it's standalone (default PATH='root.pem')
  -c,   --cert=PATH                               server public-cert path (.cer,.crt,.pem) (default PATH='cert.pem')
  -k,   --key=PATH                                server private-key path (.cer,.crt,.pem) (default PATH='cert.key')
        --client-auth                             enable client cert authentication (default=false)
        --tls-version                             tls-version: 0,1,2,3 (default=2)
  [Tool]
  -pp, --pid-path=PATH                            The pid filepath (default PATH='/var/run/$APPNAME/$APPNAME.pid')
  -s,  --stop,--shutdown                          stop/shutdown the running server (default=false)

Global Options:
  [Misc]
          --config=[Locations of config files]    load config files from where you specified (default [Locations of config files]=)
  -q,     --quiet                                 No more screen output. [env: QUITE] (default=false)
  -trace, --trace,--tr                            enable trace mode for tcp/mqtt send/recv data dump [env: TRACE] (default=false)
  -v,     --verbose                               Show this help screen [env: VERBOSE] (default=false)

Type '-h'/'-?' or '--help' to get command help screen.
More: '-D'/'--debug'['--env'|'--raw'|'--more'], '-V'/'--version', '-#'/'--build-info', '--no-color', '--strict-mode', '--no-env-overrides'...

start the server:

❯ go run ./cli tcp server -tls
2020-08-14T17:16:53.782+0800	INFO	go-socketlib/tcp/server/server.go:38	Starting server (tcp)... cmdr.InDebugging = false
2020-08-14T17:16:53.793+0800	INFO	go-socketlib/tcp/server/server.go:70	PID (79656) file created at: /var/run/tcp-tool/tcp-tool.pid
2020-08-14T17:16:53.793+0800	INFO	go-socketlib/tcp/server/server.go:106	Listening on :1983 with TLS enabled.

Start the client:

$ go run ./cli/c2 tcp client -tls -k
...
2020-08-14T17:32:25.279+0800	DEBUG	go-socketlib/tcp/client/client.go:129	 #99 sent

Write the server/client protocol interceptor with yours

By using Interceptor and ClientInterceptor, you can attach a protocol interceptor onto bare metal socketlib server/client.

For example (from our CoAP impl):

func AttachToCmdr(cmd cmdr.OptCmd, opts ...server.CmdrOpt) {

	// server

	var pis = pi.NewCoAPInterceptor()
	// var pisOpt server.Opt
	// pisOpt = server.WithServerProtocolInterceptor(pis)
	// opt1 := server.WithCmdrServerOptions(pisOpt)
	opt1 := server.WithCmdrServerProtocolInterceptor(pis)
	opt2 := server.WithCmdrPort(0)
	opt3 := server.WithCmdrCommandAction(server.DefaultLooper)
	opt4 := server.WithCmdrUDPMode(true)
	opt5 := server.WithCmdrPrefixPrefix("coap")

	server.AttachToCmdr(cmd, append(opts, opt1, opt2, opt3, opt4, opt5)...)

	serverCmdrOpt := cmdr.NewCmdFrom(cmd.ToCommand().FindSubCommand("server"))
	cmdr.NewBool().
		Titles("dry-run", "dr", "dryrun").
		Description("In dry-run mode, arguments will be parsed, tcp listener will not be stared.").
		Group("zzz1.Dry Run").
		AttachTo(serverCmdrOpt)

	// client

	var pic = pi.NewCoAPClientInterceptor()
	//optCx1 := client.WithClientProtocolInterceptor(pic)
	//ox1 := client.WithCmdrClientOptions(optCx1)
	ox1 := client.WithCmdrClientProtocolInterceptor(pic)
	ox2 := client.WithCmdrPort(0)                                        // get ports configs from config file
	ox3 := client.WithCmdrUDPMode(true)                                  // enable udp mode and loop (udpLoop)
	ox4 := client.WithCmdrCommandAction(client.DefaultLooper)            // default internal looper
	ox5 := client.WithCmdrMainLoop(pic.(client.MainLoopHolder).MainLoop) // coapMainLoop will block the main thread to exit to OS
	ox6 := client.WithCmdrPrefixPrefix("coap")                           // prefix of prefix is used for loading the coap section from config file

	client.AttachToCmdr(cmd, ox1, ox2, ox3, ox4, ox5, ox6)

	clientCmdrOpt := cmdr.NewCmdFrom(cmd.ToCommand().FindSubCommand("client"))
	cmdr.NewBool().
		Titles("dry-run", "dr", "dryrun").
		Description("In dry-run mode, arguments will be parsed, tcp listener will not be stared.").
		Group("zzz1.Testers").
		AttachTo(clientCmdrOpt)
	cmdr.NewBool().
		Titles("try-debug", "try").
		Description("In try-debug mode, A continuous send/recv (to coap.me) processing will be started automatically.").
		Group("zzz1.Testers").
		AttachTo(clientCmdrOpt)
	clientCmdrOpt.ToCommand().FindFlag("host").DefaultValue = remoteCaliforniumEclipseOrg // remoteCaliforniumEclipseOrg
}

Contrib

Welcome

LICENSE

MIT