enet为替代TCP的可靠udp传输的一种实现,用于提高数据的传输速度,缩短传输的延时。

一、准备go文件

在github的项目链接(

找到客户端和服务器端的代码,保存为enet_client.go和enet_server.go两个文件。

1)enet_client.go

package main

import (
	"github.com/codecat/go-enet"
	"github.com/codecat/go-libs/log"
)

func main() {
	// Initialize enet
	enet.Initialize()

	// Create a client host
	client, err := enet.NewHost(nil, 1, 1, 0, 0)
	if err != nil {
		log.Error("Couldn't create host: %s", err.Error())
		return
	}

	// Connect the client host to the server
	peer, err := client.Connect(enet.NewAddress("127.0.0.1", 8095), 1, 0)
	if err != nil {
		log.Error("Couldn't connect: %s", err.Error())
		return
	}

	// The event loop
	for true {
		// Wait until the next event
		ev := client.Service(1000)

		// Send a ping if we didn't get any event
		if ev.GetType() == enet.EventNone {
			peer.SendString("ping", 0, enet.PacketFlagReliable)
			continue
		}

		switch ev.GetType() {
		case enet.EventConnect: // We connected to the server
			log.Info("Connected to the server!")

		case enet.EventDisconnect: // We disconnected from the server
			log.Info("Lost connection to the server!")

		case enet.EventReceive: // The server sent us data
			packet := ev.GetPacket()
			log.Info("Received %d bytes from server", len(packet.GetData()))
			packet.Destroy()
		}
	}

	// Destroy the host when we're done with it
	client.Destroy()

	// Uninitialize enet
	enet.Deinitialize()
}

2)enet_server.go

import (
        "github.com/codecat/go-enet"
        "github.com/codecat/go-libs/log"
)

func main() {
        // Initialize enet
        enet.Initialize()

        // Create a host listening on 0.0.0.0:8095
        host, err := enet.NewHost(enet.NewListenAddress(8095), 32, 1, 0, 0)
        if err != nil {
                log.Error("Couldn't create host: %s", err.Error())
                return
        }

        // The event loop
        for true {
                // Wait until the next event
                ev := host.Service(1000)

                // Do nothing if we didn't get any event
                if ev.GetType() == enet.EventNone {
                        continue
                }

                switch ev.GetType() {
                case enet.EventConnect: // A new peer has connected
                        log.Info("New peer connected: %s", ev.GetPeer().GetAddress())

                case enet.EventDisconnect: // A connected peer has disconnected
                        log.Info("Peer disconnected: %s", ev.GetPeer().GetAddress())

                case enet.EventReceive: // A peer sent us some data
                        // Get the packet
                        packet := ev.GetPacket()

                        // We must destroy the packet when we're done with it
                        defer packet.Destroy()

                        // Get the bytes in the packet
                        packetBytes := packet.GetData()

                        // Respond "pong" to "ping"
                        if string(packetBytes) == "ping" {
                                ev.GetPeer().SendString("pong", ev.GetChannelID(), enet.PacketFlagReliable)
                                continue
                        }

                        // Disconnect the peer if they say "bye"
                        if string(packetBytes) == "bye" {
                                log.Info("Bye!")
                                ev.GetPeer().Disconnect(0)
                                continue
                        }
                }
        }

        // Destroy the host when we're done with it
        host.Destroy()

        // Uninitialize enet
        enet.Deinitialize()
}

二、编译程序

编译之前需要安装libenet-dev库,因为 go-enet只是针对libenet的库的简单go语言封装。

sudo apt install libenet-dev

服务器端程序编译:go build enet_server.go

发现少了两个依赖的库(go-enet和go-libs)

go build enet_server.go
enet_server.go:4:2: cannot find package "github.com/codecat/go-enet" in any of:
        /home/shane/.gvm/gos/go1.13.3/src/github.com/codecat/go-enet (from $GOROOT)
        /home/shane/.gvm/pkgsets/go1.13.3/global/src/github.com/codecat/go-enet (from $GOPATH)
enet_server.go:5:2: cannot find package "github.com/codecat/go-libs/log" in any of:
        /home/shane/.gvm/gos/go1.13.3/src/github.com/codecat/go-libs/log (from $GOROOT)
        /home/shane/.gvm/pkgsets/go1.13.3/global/src/github.com/codecat/go-libs/log (from $GOPATH)

客户端程序编译:go build enet_client.go (出现与服务器端程序编译相同的错误

三、获取依赖的库文件

因为go get经常容易失败,所以需要先设置代理,使用国内七牛云的 go module 镜像。

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

注: 低版本的go不支持-w的选项,会报如下错误。

 go env -w GO111MODULE=on
flag provided but not defined: -w
usage: env [-json] [var ...]
Run 'go help env' for details.

获取两个依赖库,go-enet和go-libs

go get github.com/codecat/go-enet

go get github.com/codecat/go-libs

四、程序运行

./enet_server

./enet_server
21:50:02.915 |  INFO | New peer connected: 127.0.0.1

./enet_client

 ./enet_client
21:50:02.914 |  INFO | Connected to the server!
21:50:03.919 |  INFO | Received 4 bytes from server
21:50:04.922 |  INFO | Received 4 bytes from server

后记

看起来这两个客户端和服务器端的两个文件的代码量不大,主要是因为大部分的实现细节在所依赖的模块里面。