gosocket

package module
v0.0.0-...-9c42eb2 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2020 License: MIT Imports: 13 Imported by: 0

README

Gosocket

Gosocket is a simple, lightweight, session, heartbeat socket library written in Go (Golang). Supports TCP now. UDP and WS will be supported in future. If you need small and simple enough, you will love Gosocket.

Example client

demo

Build example client

cd gosocket/cli
./buildDarwin.sh

Start server

cd gosocket/cli
./gosocket_darwin_amd64 server -l 0.0.0.0:8888 -d true

Start client

cd gosocket/cli
./gosocket_darwin_amd64 client -t 127.0.0.1:8888 -d true

Installation

To install Gin package, you need to install Go and set your Go workspace first.

  1. The first need Go installed (version 1.11+ is required), then you can use the below Go command to install Gin.
$ go get -u github.com/thiinbit/gosocket
  1. Import it in your code:
import "github.com/thiinbit/gosocket"

QuickStart

(see server_test.go -> func TestUsageQuickStart)

Part.1 Create Server step.
  1. Create server message listener. (Process on message received from client.)
// Implement server OnMessageListener interface. Just like code below. 
//     type MessageListener interface {
//         OnMessage(ctx context.Context, message interface{}, session *Session)
//     }

// TestExampleServerMessageListener !required listener: listening server receives message.
type TestExampleServerMessageListener struct{}

func (tl *TestExampleServerMessageListener) OnMessage(ctx context.Context, message interface{}, session *Session) {
	log.Print("Server received message: ", message)

	// Reply to Client "Hi!" when received "Hello!".
	if message == "Hello!" {
		session.SendMessage("Hi!")
	}
}
  1. Create TCPServer and run it.
	// New TCPServer, register MessageListener to the server, and startup it.
	server, _ := NewTCPServer("[::1]:8888").
		RegisterMessageListener(&TestExampleServerMessageListener{}). // Required
		Run()

	//   - And now, congratulations! a tcp server is ready.

	//  Stop the server when it is finished.
	go func() {
		<-time.NewTimer(10 * time.Second).C

		server.Stop()
	}()
Part.2 Create Client
  1. Create client message listener. (Process on message received from server.)
// Implement ClientMessageListener interface. Just like code below.
//     type ClientMessageListener interface {
//         OnMessage(ctx context.Context, message interface{}, cli *TCPClient)
//     }

// TestExampleClientListener !required listener: listening client receives message.
type TestExampleClientListener struct{}

func (cl *TestExampleClientListener) OnMessage(ctx context.Context, message interface{}, cli *TCPClient) {
	log.Print("Client received message: ", message)

	// Reply to Server "Nice weather!" when received "Hi!"
	if message == "Hi!" {
		cli.SendMessage("Nice weather!")
	}
}

2. Create TCPClient, dial to server, and say "Hello!".
	// New TCPClient, register ClientMessageListener to the client, and dial to server.
	client, _ := NewTcpClient("[::1]:8888").
		RegisterMessageListener(&TestExampleClientListener{}).
		Dial()

    //   - And now, congratulations! a tcp client is ready.

	// Say "Hello!" to server.
	client.SendMessage("Hello!")

	// Hangup the client when it is finished.
	go func() {
		<-time.NewTimer(10 * time.Second).C

		client.Hangup("It should be hangup now!")
	}()

More Usage

// TODO: Supplement more detailed documents

All features of the Server
	server, _ := NewTCPServer("[::1]:8888").
		RegisterMessageListener(&TestExampleServerMessageListener{}). // Required: Listening receives message
		RegisterSessionListener(&TestExampleSessionListener{}). // Optional: Listening session create/close
		SetCodec(&TestExampleCodec{}). // Optional: Custom codec. Default codec directly to binary. You can choose to use JSON, protobuf and other methods you want to use.
		SetDebugMode(false). // Optional: The debug log will be printed in the DebugMode true, and the DebugMode false will not.
		// The parameters above need to be paid attention to, the parameters below do not need to be paid attention to.
		SetMaxPacketBodyLength(4*1024*1024). // Optional: Maximum bytes per message. Default 4M.
		SetHeartbeat(13*time.Second). // Optional: Heartbeat time. Default 13 seconds. Heartbeat only if no message is received. Heartbeat time must less than readDeadline!
		SetDefaultSessionReadDeadline(42*time.Second). // Optional: Read deadline time. Default 42 seconds. Time out automatically close session. It means that if the server don't receive any message or heartbeat for more than 42 seconds, will close the session.
		SetDefaultSessionWriteDeadline(5*time.Second). // Optional: Write deadline time. Default 5 seconds. If a message in the sending state is not sent for more than 5 seconds, the session will be automatically closed.
		//                                             // - In addition, the heartbeat/read/writeDeadline can be set individually for each session, and you can modify the heartbeat/readWriteDeadline of a single session at any time during runtime.
		SetLogger( // Optional: You can customize the logger. Compatible with go original log. Default is go original log with prefix [Gosocket]. You can use any log just implement these nine functions (Print(v ...interface{}), Printf(format string, v ...interface{}), Println(v ...interface{}), Fatal(v ...interface{}), Fatalf(format string, v ...interface{}), Fatalln(v ...interface{}), Panic(v ...interface{}), Panicf(format string, v ...interface{}), Panicln(v ...interface{})).
			log.New(os.Stderr, "[Gosocket-Debug]", log.LstdFlags), // Debug logger.
			log.New(os.Stderr, "[Gosocket]", log.LstdFlags)). // Release logger.
		Run() // Startup
All features of the Client
client, _ := NewTcpClient("[::1]:8888").
		RegisterMessageListener(&TestExampleClientListener{}). // Required: Listening receives message
		SetCodec(&TestExampleCodec{}). // Optional: Custom codec. Default codec directly to binary. You can choose to use JSON, protobuf and other methods you want to use.
		// The parameters above need to be paid attention to, the parameters below do not need to be paid attention to.
		SetMaxPacketBodyLength(4*1024*1024).
		SetSessionReadDeadline(42*time.Second).
		SetSessionWriteDeadline(24*time.Hour).
		SetLogger( // Optional: You can customize the logger. Compatible with go original log. Default is go original log with prefix [Gosocket]. You can use any log just implement these nine functions (Print(v ...interface{}), Printf(format string, v ...interface{}), Println(v ...interface{}), Fatal(v ...interface{}), Fatalf(format string, v ...interface{}), Fatalln(v ...interface{}), Panic(v ...interface{}), Panicf(format string, v ...interface{}), Panicln(v ...interface{})).
			log.New(os.Stderr, "[Gosocket-Debug]", log.LstdFlags), // Debug logger.
			log.New(os.Stderr, "[Gosocket]", log.LstdFlags)). // Release logger.
		Dial()
Custom Code and Session Listener example.
// TestExampleSessionListener !optional listener: listening server session create/close event.
// - When you want do something on session create/close.
type TestExampleSessionListener struct {
}

func (t TestExampleSessionListener) OnSessionCreate(s *Session) {
	log.Printf("Server session create. sID: %s, remote: %s, createTime: %s, lastActive: %s",
		s.SID(), s.RemoteAddr(), s.CreateTime(), s.LastActive())
}

func (t TestExampleSessionListener) OnSessionClose(s *Session) {
	log.Printf("Server session close. sID: %s, remote: %s, createTime: %s, lastActive: %s",
		s.SID(), s.RemoteAddr(), s.CreateTime(), s.LastActive())
}

// TestExampleCodec you can custom your owner message codec, like use JSON, protobuf, more and more.
// - a plain string codec.
type TestExampleCodec struct {
}

func (d TestExampleCodec) Encode(message interface{}) ([]byte, error) {
	// You can use JSON, protobuf and more other methods to serialize
	return []byte(fmt.Sprintf("%v", message)), nil
}

func (d TestExampleCodec) Decode(bytes []byte) (interface{}, error) {
	// You can use JSON, protobuf and more other methods to deserialize
	return string(bytes), nil
}

Client SDKs

TODO:
  1. Supplement more detailed documents and use cases
  2. Swift client sdk -> first version done.
  3. Java client sdk -> first version done.
  4. Support UDP, WEBSOCKET.
  5. Keep it's simple.
Ver:

0.0.1:

  • First version. Base functions. TCP message, heartbeat, session management, and more.

0.0.2:

  • Add a client example.
  • Some fix, adj.

Documentation

Index

Constants

View Source
const (
	Preparing = "Preparing"
	Running   = "Running"
	Stop      = "Stop"
)

Server status

View Source
const (
	HeartbeatCmdPing byte = 0
	HeartbeatCmdPong byte = 1
)

Heartbeat cmd

View Source
const (
	DEBUG   = "DEBUG"
	RELEASE = "RELEASE"
)

Environment info

View Source
const (
	PacketVersion          byte = 0x2A // 101010 -> 42    // Packet ver:    42 -> 43 -> 44 -> ...
	PacketHeartbeatVersion byte = 0xFF // 11111111 -> 255 // Heartbeat ver: 255 -> 254- > 253 -> ...
)
View Source
const Version = "0.0.1"

Variables

View Source
var (
	DefaultDebugLogger = log.New(os.Stderr, "[Gosocket-Debug]", log.LstdFlags)
	DefaultLogger      = log.New(os.Stderr, "[Gosocket]", log.LstdFlags)
)
View Source
var ErrTimeout error = &TimeoutError{}

ErrTimeout is returned for an expired deadline.

Functions

func Blue

func Blue(s interface{}) string

func Green

func Green(s interface{}) string

func Magenta

func Magenta(s interface{}) string

func Red

func Red(s interface{}) string

func Yellow

func Yellow(s interface{}) string

Types

type BroadcastServerMessageListener

type BroadcastServerMessageListener struct{}

======== ======== Broadcast server message receive listener ======== ======== BroadcastServerMessageListener

func (*BroadcastServerMessageListener) OnMessage

func (tl *BroadcastServerMessageListener) OnMessage(ctx context.Context, message interface{}, session *Session)

BroadcastServerMessageListener impl

type ClientCodec

type ClientCodec interface {
	// Encode body to bytes
	Encode(ctx context.Context, message interface{}, cli *TCPClient) ([]byte, error)
	// Decode from bytes
	Decode(ctx context.Context, bytes []byte, cli *TCPClient) (interface{}, error)
}

ClientCodec

type ClientDefaultCodec

type ClientDefaultCodec struct {
}

func (ClientDefaultCodec) Decode

func (d ClientDefaultCodec) Decode(ctx context.Context, bytes []byte, cli *TCPClient) (interface{}, error)

func (ClientDefaultCodec) Encode

func (d ClientDefaultCodec) Encode(ctx context.Context, message interface{}, cli *TCPClient) ([]byte, error)

type ClientMessageListener

type ClientMessageListener interface {
	OnMessage(ctx context.Context, message interface{}, cli *TCPClient)
}

type ClientPacketHandler

type ClientPacketHandler interface {
	PacketReceived(ctx context.Context, packet *Packet, cli *TCPClient)
	PacketSend(ctx context.Context, packet *Packet, cli *TCPClient)
}

ClientPacketHandler

type Codec

type Codec interface {
	// Encode body to bytes
	Encode(ctx context.Context, message interface{}, session *Session) ([]byte, error)
	// Decode from bytes
	Decode(ctx context.Context, bytes []byte, session *Session) (interface{}, error)
}

Codec

type ConnectHandler

type ConnectHandler interface {
	OnConnect(ctx context.Context, conn *net.TCPConn, tcpSer *TCPServer)
}

ConnectHandler on connect accept processor

type DebugLogger

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

func (*DebugLogger) Fatal

func (d *DebugLogger) Fatal(v ...interface{})

func (*DebugLogger) Fatalf

func (d *DebugLogger) Fatalf(format string, v ...interface{})

func (*DebugLogger) Fatalln

func (d *DebugLogger) Fatalln(v ...interface{})

func (*DebugLogger) Panic

func (d *DebugLogger) Panic(v ...interface{})

func (*DebugLogger) Panicf

func (d *DebugLogger) Panicf(format string, v ...interface{})

func (*DebugLogger) Panicln

func (d *DebugLogger) Panicln(v ...interface{})

func (*DebugLogger) Print

func (d *DebugLogger) Print(v ...interface{})

func (*DebugLogger) Printf

func (d *DebugLogger) Printf(format string, v ...interface{})

func (*DebugLogger) Println

func (d *DebugLogger) Println(v ...interface{})

func (*DebugLogger) SetDebugMode

func (d *DebugLogger) SetDebugMode(on bool)

type DefaultCodec

type DefaultCodec struct {
}

func (DefaultCodec) Decode

func (d DefaultCodec) Decode(ctx context.Context, bytes []byte, session *Session) (interface{}, error)

func (DefaultCodec) Encode

func (d DefaultCodec) Encode(ctx context.Context, message interface{}, session *Session) ([]byte, error)

type ExampleClientMessageListener

type ExampleClientMessageListener struct{}

======== ======== Example client message receive listener ======== ========

func (ExampleClientMessageListener) OnMessage

func (t ExampleClientMessageListener) OnMessage(ctx context.Context, message interface{}, cli *TCPClient)

type ExampleServerMessageListener

type ExampleServerMessageListener struct{}

======== ======== Example server server message receive listener ======== ========

func (ExampleServerMessageListener) OnMessage

func (e ExampleServerMessageListener) OnMessage(ctx context.Context, message interface{}, session *Session)

type ExampleSessionListener

type ExampleSessionListener struct{}

======== ======== Example server session create/close listener ======== ========

func (ExampleSessionListener) OnSessionClose

func (t ExampleSessionListener) OnSessionClose(s *Session)

func (ExampleSessionListener) OnSessionCreate

func (t ExampleSessionListener) OnSessionCreate(s *Session)

type Logger

type Logger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Println(v ...interface{})
	Fatal(v ...interface{})
	Fatalf(format string, v ...interface{})
	Fatalln(v ...interface{})
	Panic(v ...interface{})
	Panicf(format string, v ...interface{})
	Panicln(v ...interface{})
}

type MessageListener

type MessageListener interface {
	OnMessage(ctx context.Context, message interface{}, session *Session)
}

MessageListener message processor interface Usage:

type Packet

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

func NewHeartbeatPacket

func NewHeartbeatPacket(cmd byte) *Packet

Build heartbeat packet. cmd -> 0: ping; 1: pong - see const HeartbeatCmdPing, HeartbeatCmdPong

func NewPacket

func NewPacket(ver byte, len uint32, packet []byte, checksum uint32) *Packet

func (*Packet) Body

func (p *Packet) Body() []byte

Body return the packet body

func (*Packet) Checksum

func (p *Packet) Checksum() bool

Checksum return checksum is success

func (*Packet) Len

func (p *Packet) Len() uint32

Len return the packet body length

func (*Packet) Ver

func (p *Packet) Ver() byte

Ver return the packet version

type PacketHandler

type PacketHandler interface {
	PacketReceived(ctx context.Context, packet *Packet, session *Session)
	PacketSend(ctx context.Context, packet *Packet, session *Session)
}

PacketHandler on packet receive processor

type Session

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

ClientSession

func NewSession

func NewSession(conn *net.TCPConn, readDeadline time.Duration, WriteDeadline time.Duration, heartbeat time.Duration, serverRef *TCPServer) *Session

func (*Session) Attr

func (s *Session) Attr(key string) interface{}

GetAttr get attribute by key

func (*Session) CloseSession

func (s *Session) CloseSession(reason string)

func (*Session) CreateTime

func (s *Session) CreateTime() time.Time

CreateTime return the session create time

func (*Session) Heartbeat

func (s *Session) Heartbeat() time.Duration

func (*Session) IsClosed

func (s *Session) IsClosed() bool

IsClosed return the session is closed

func (*Session) LastActive

func (s *Session) LastActive() time.Time

LastActive return the session last active time. (update on create, close, send packet, receive packet)

func (*Session) ReadDeadlin

func (s *Session) ReadDeadlin() time.Duration

func (*Session) RemoteAddr

func (s *Session) RemoteAddr() string

RemoteAddr return string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80")

func (*Session) SID

func (s *Session) SID() string

SID return the session ID

func (*Session) SendMessage

func (s *Session) SendMessage(message interface{})

func (*Session) ServerRef

func (s *Session) ServerRef() *TCPServer

ServerRef return the server ref of session

func (*Session) SetAttr

func (s *Session) SetAttr(key string, val string) *Session

SetAttr set attribute key, value

func (*Session) SetHeartbeat

func (s *Session) SetHeartbeat(heartbeat time.Duration)

func (*Session) SetReadDeadline

func (s *Session) SetReadDeadline(readDeadine time.Duration)

func (*Session) SetWriteDeadline

func (s *Session) SetWriteDeadline(writeDeadline time.Duration)

func (*Session) UpdateLastActive

func (s *Session) UpdateLastActive()

UpdateLastActive update the session last active time.

func (*Session) WriteDeadline

func (s *Session) WriteDeadline() time.Duration

WriteDeadLine return the session write deadline

type SessionListener

type SessionListener interface {
	OnSessionCreate(session *Session)
	OnSessionClose(session *Session)
}

type SessionWriter

type SessionWriter interface {
	Write()
}

type TCPClient

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

TCPClient the tcp server struct

func NewTcpClient

func NewTcpClient(serAddr string) *TCPClient

NewTcpClient create a new tcp server Usage: * TODO: write usage

func (*TCPClient) Dial

func (cli *TCPClient) Dial() (*TCPClient, error)

func (*TCPClient) Hangup

func (cli *TCPClient) Hangup(reason string)

func (*TCPClient) RegisterMessageListener

func (cli *TCPClient) RegisterMessageListener(listener ClientMessageListener) *TCPClient

func (*TCPClient) RemoteAddr

func (cli *TCPClient) RemoteAddr() string

func (*TCPClient) SendMessage

func (cli *TCPClient) SendMessage(msg interface{}) error

func (*TCPClient) SetCodec

func (cli *TCPClient) SetCodec(codec ClientCodec) *TCPClient

func (*TCPClient) SetDebugMode

func (cli *TCPClient) SetDebugMode(on bool) *TCPClient

func (*TCPClient) SetLogger

func (cli *TCPClient) SetLogger(debugLogger Logger, logger Logger) *TCPClient

func (*TCPClient) SetMaxPacketBodyLength

func (cli *TCPClient) SetMaxPacketBodyLength(maxMsgBodyLen uint32) *TCPClient

func (*TCPClient) SetSessionReadDeadline

func (cli *TCPClient) SetSessionReadDeadline(read time.Duration) *TCPClient

func (*TCPClient) SetSessionWriteDeadline

func (cli *TCPClient) SetSessionWriteDeadline(write time.Duration) *TCPClient

func (*TCPClient) UpdateLastActive

func (cli *TCPClient) UpdateLastActive()

type TCPServer

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

TCPServer the tcp server struct

func NewTCPServer

func NewTCPServer(addr string) *TCPServer

NewTCPServer create a new tcp server Usage:

 ============================================
  ! Detail see: server_test.go OR README.md!
 ============================================
	// ==== ==== Server QuickStart ==== ====

	// 1. Implement server OnMessageListener interface. see code above.
	//     type MessageListener interface {
	//         OnMessage(ctx context.Context, message interface{}, session *Session)
	//     }

	// 2. New TCPServer, register MessageListener to the server, and startup it.
	//    - And now, congratulations! a tcp server is ready.
	server, _ := NewTCPServer("[::1]:8888").
		RegisterMessageListener(&TestExampleServerMessageListener{}). // Required
		Run()

	// 3. Stop the server when it is finished.
	go func() {
		<-time.NewTimer(10 * time.Second).C

		server.Stop()
	}()

	// ==== ==== Client QuickStart ==== ====

	// 1. Implement ClientMessageListener interface. see code above.
	//     type ClientMessageListener interface {
	//         OnMessage(ctx context.Context, message interface{}, cli *TCPClient)
	//     }

	// 2. New TCPClient, register ClientMessageListener to the client, and dial to server.
	//    - And now, congratulations! a tcp client is ready.
	client, _ := NewTcpClient("[::1]:8888").
		RegisterMessageListener(&TestExampleClientListener{}).
		Dial()

	// 3. Say "Hello!" to server.
	client.SendMessage("Hello!")

	// 4. Hangup the client when it is finished.
	go func() {
		<-time.NewTimer(6 * time.Second).C

		client.Hangup("It should be hangup now!")
	}()
 ============================================
  ! Detail see: server_test.go OR README.md!
 ============================================

func (*TCPServer) RegisterMessageListener

func (ts *TCPServer) RegisterMessageListener(listener MessageListener) *TCPServer

func (*TCPServer) RegisterSessionListener

func (ts *TCPServer) RegisterSessionListener(listener SessionListener) *TCPServer

func (*TCPServer) Run

func (ts *TCPServer) Run() (*TCPServer, error)

func (*TCPServer) Sessions

func (ts *TCPServer) Sessions() map[string]*Session

func (*TCPServer) SetCodec

func (ts *TCPServer) SetCodec(codec Codec) *TCPServer

func (*TCPServer) SetDebugMode

func (ts *TCPServer) SetDebugMode(on bool) *TCPServer

func (*TCPServer) SetDefaultSessionReadDeadline

func (ts *TCPServer) SetDefaultSessionReadDeadline(read time.Duration) *TCPServer

SetDefaultSessionReadDeadline session timeout if can not read any thing in this time

func (*TCPServer) SetDefaultSessionWriteDeadline

func (ts *TCPServer) SetDefaultSessionWriteDeadline(write time.Duration) *TCPServer

func (*TCPServer) SetHeartbeat

func (ts *TCPServer) SetHeartbeat(heartbeat time.Duration) *TCPServer

func (*TCPServer) SetLogger

func (ts *TCPServer) SetLogger(debugLogger Logger, logger Logger) *TCPServer

func (*TCPServer) SetMaxPacketBodyLength

func (ts *TCPServer) SetMaxPacketBodyLength(maxLenBytes uint32) *TCPServer

func (*TCPServer) Stop

func (ts *TCPServer) Stop() error

type TimeoutError

type TimeoutError struct{}

TimeoutError is returned for an expired deadline.

func (*TimeoutError) Error

func (e *TimeoutError) Error() string

Implement the net.Error interface.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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