在网络世界里,进程间的通信离不开socket,主要分为TCP SocketUDP Socket

下面以TCP 为例,分别写一下服务端客户端

这里要做的客户端服务端,在连接建立后,都可以接收和发送消息。

首先定义三个事件回调:

// listener.go

package socketer

import "net"

// ConnectListener 连接建立回调
type ConnectListener func(conn net.Conn)

// ReceiveListener 收到消息回调
type ReceiveListener func(data []byte, conn net.Conn)

// CloseListener 连接关闭事件
type CloseListener func(conn net.Conn)

服务端

服务端主要实现:

  • 初始化一个服务端NewServer()
  • 定义事件回调OnConnect() OnReceive() OnClose()
  • 开始监听Listen()
// server.go

package socketer

import (
    "bufio"
    "io"
    "net"
)

type Server struct {
    listener net.Listener

    address string
    network string

    closeListener   CloseListener
    receiveListener ReceiveListener
    connectListener ConnectListener
}

func NewServer(network, address string) *Server {
    return &Server{
        network: network,
        address: address,
    }
}

func (s *Server) OnConnect(l ConnectListener) {
    s.connectListener = l
}

func (s *Server) OnReceive(l ReceiveListener) {
    s.receiveListener = l
}

func (s *Server) OnClose(l CloseListener) {
    s.closeListener = l
}

func (s *Server) Send(conn net.Conn, data []byte) (int, error) {
    return conn.Write(data)
}

func (s *Server) Close(conn net.Conn) error {
    err := conn.Close()
    if s.closeListener != nil {
        s.connectListener(conn)
    }
    return err
}

func (s *Server) Listen() error {
    var err error
    s.listener, err = net.Listen(s.network, s.address)
    if err != nil {
        return err
    }

    for {
        conn, err := s.listener.Accept()
        if err != nil {
            continue
        }
        if s.connectListener != nil {
            s.connectListener(conn)
        }
        go s.accept(conn)
    }
}

func (s *Server) accept(conn net.Conn) {
    defer conn.Close()

    reader := bufio.NewReader(conn)

    for {
        message, err := reader.ReadBytes('\n')
        if err != nil {
            if err == io.EOF {
                s.Close(conn)
            }
            break
        }

        if s.receiveListener != nil {
            go s.receiveListener(message, conn)
        }
    }
}

客户端

客户端主要实现

  • 初始化一个客户端NewClient()
  • 定义事件回调OnConnect() OnReceive() OnClose()
  • 发送消息Send()
  • 接收消息Recv(),只接收一条消息
  • 保持连接Open(),并持续接收消息,并触发消息回调
// client.go

package socketer

import (
    "bufio"
    "net"
)

type Client struct {
    Conn net.Conn

    address string
    network string

    closeListener   CloseListener
    receiveListener ReceiveListener
    connectListener ConnectListener
}

func NewClient(network, address string) (*Client, error) {
    var err error
    client := &Client{
        address: address,
        network: network,
    }
    err = client.dial()
    return client, err
}

func (c *Client) dial() error {
    var err error
    c.Conn, err = net.Dial(c.network, c.address)
    if c.connectListener != nil {
        c.connectListener(c.Conn)
    }
    return err
}

func (c *Client) Send(data []byte) (int, error) {
    return c.Conn.Write(data)
}

func (c *Client) OnConnect(l ConnectListener) {
    c.connectListener = l
}

func (c *Client) OnReceive(l ReceiveListener) {
    c.receiveListener = l
}

func (c *Client) OnClose(l CloseListener) {
    c.closeListener = l
}

func (c *Client) Close() error {
    err := c.Conn.Close()
    if c.closeListener != nil {
        c.closeListener(c.Conn)
    }
    return err
}

func (c *Client) Recv() ([]byte, error) {
    reader := bufio.NewReader(c.Conn)

    return reader.ReadBytes('\n')
}

func (c *Client) Open() {
    reader := bufio.NewReader(c.Conn)
    defer c.Conn.Close()

    for {
        message, err := reader.ReadBytes('\n')
        if err != nil {
            break
        }
        if c.receiveListener != nil {
            go c.receiveListener(message, c.Conn)
        }
    }
}

主要用法

首先服务端定义好消息回调并开始监听:

serv := NewServer("tcp", "127.0.0.1:6000")

// 消息回调
serv.OnReceive(func(data []byte, conn net.Conn) {
    fmt.Println("Server Received: ", string(data))
    serv.Send(conn, []byte("ok\n"))
})

// 开始监听
serv.Listen()

然后在客户端,建立连接,并发送消息,接收消息:

client, err := NewClient("tcp", "127.0.0.1:6000")
if err != nil {
    panic(err)
}

defer client.Close()

// 消息回调
client.OnReceive(func(data []byte, conn net.Conn) {
    fmt.Println("Client Received: ", string(data))
})

// 发送消息
client.Send([]byte("啊哈哈\n"))

data, err := client.Recv()
if err != nil {
    panic(err)
}

fmt.Println("Client Received: ", string(data))

// 如果想保持长连接,持续接收发送消息
client.Open()