Skip to content

lackone/go-epoll

Repository files navigation

go-epoll

go 实现 epoll,基于边缘触发模式。

示例

服务端代码:

package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	go_epoll "github.com/lackone/go-epoll"
	"log"
)

type EnDecode struct {
}

func (e *EnDecode) Encode(data []byte) ([]byte, error) {
	length := uint32(4 + len(data))
	buf := &bytes.Buffer{}
	err := binary.Write(buf, binary.BigEndian, length)
	if err != nil {
		return nil, err
	}
	err = binary.Write(buf, binary.BigEndian, data)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// 注意,只有解码这里有点特殊,因为必须要解码一个完整的包,因为binary.Read会移动buffer中的start下标,如果解码未成功,需要重置start
func (e *EnDecode) Decode(reader *go_epoll.Buffer) (data []byte, err error) {
	start := reader.GetStart()

	defer func() {
		if err != nil {
			//如果出错,则重置start
			reader.SetStart(start)
		}
	}()

	var length uint32
	//尝试读取4个字节数据
	_, err = reader.TryGet(4)
	if err != nil {
		return nil, err
	}

	err = binary.Read(reader, binary.BigEndian, &length)
	if err != nil {
		return nil, err
	}

	data = make([]byte, length-4)

	//尝试读取data长度的字节数据
	_, err = reader.TryGet(len(data))
	if err != nil {
		return nil, err
	}
	err = binary.Read(reader, binary.BigEndian, data)
	if err != nil {
		return nil, err
	}

	return data, nil
}

type Handler struct {
}

func (h *Handler) OnConnect(conn *go_epoll.Conn) {
	fmt.Println("连接成功", conn.GetAddr())
}

func (h *Handler) OnData(conn *go_epoll.Conn, data []byte) {
	fmt.Printf("get client[%s] data : %s\n", conn.GetAddr(), string(data))
	conn.Write(data)
}

func (h *Handler) OnError(conn *go_epoll.Conn) {
	fmt.Println("出错", conn.GetAddr())
}

func (h *Handler) OnClose(conn *go_epoll.Conn) {
	fmt.Println("关闭连接", conn.GetAddr())
}

func main() {
	go_epoll.SetLimit()

	server, err := go_epoll.NewTcpServer("127.0.0.1:8080", go_epoll.EpollType, 10, 256, 20)
	if err != nil {
		log.Fatalln(err)
	}
	defer server.Close()

	server.SetHandler(&Handler{})

	server.SetEnDecoder(&EnDecode{})

	server.Run()
}

客户端代码:

package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"net"
	"time"
)

func Encode(data []byte) ([]byte, error) {
	length := uint32(4 + len(data))
	buf := &bytes.Buffer{}
	err := binary.Write(buf, binary.BigEndian, length)
	if err != nil {
		return nil, err
	}
	err = binary.Write(buf, binary.BigEndian, data)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func Decode(reader io.Reader) ([]byte, error) {
	var length uint32
	err := binary.Read(reader, binary.BigEndian, &length)
	if err != nil {
		return nil, err
	}
	buf := make([]byte, length-4)
	err = binary.Read(reader, binary.BigEndian, buf)
	if err != nil {
		return nil, err
	}
	return buf, nil
}

func main() {
	dial, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		log.Fatalln(err)
	}

	for {
		encode, _ := Encode([]byte(time.Now().Format("2006-01-02 15:04:05")))
		dial.Write(encode)

		decode, err := Decode(dial)
		if err != nil {
			fmt.Println(err)
		}
		fmt.Println("get server data : ", string(decode))

		time.Sleep(time.Second)
	}
}

About

go 实现 epoll,基于边缘触发模式

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages