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