Skip to content

Commit

Permalink
Merge pull request #523 from panjf2000/dev
Browse files Browse the repository at this point in the history
patch: v2.3.4
  • Loading branch information
panjf2000 authored Jan 4, 2024
2 parents 0cbb2a2 + f975647 commit a509c76
Show file tree
Hide file tree
Showing 15 changed files with 219 additions and 36 deletions.
10 changes: 1 addition & 9 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
---
name: Pull request
about: Propose changes to the code
title: ''
labels: ''
assignees: ''
---

<!--
Thank you for contributing to `gnet`! Please fill this out to help us make the most of your pull request.
Thank you for contributing to `gnet`! Please fill this out to help us review your pull request more efficiently.
Was this change discussed in an issue first? That can help save time in case the change is not a good fit for the project. Not all pull requests get merged.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Setup and run golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.52.2
version: v1.55.2
args: -v -E gofumpt -E gocritic -E misspell -E revive -E godot --timeout 5m
test:
needs: lint
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_gc_opt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Setup and run golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.52.2
version: v1.55.2
args: -v -E gofumpt -E gocritic -E misspell -E revive -E godot --timeout 5m
test:
needs: lint
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_poll_opt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- name: Setup and run golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.52.2
version: v1.55.2
args: -v -E gofumpt -E gocritic -E misspell -E revive -E godot
test:
needs: lint
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_poll_opt_gc_opt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- name: Setup and run golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.52.2
version: v1.55.2
args: -v -E gofumpt -E gocritic -E misspell -E revive -E godot
test:
needs: lint
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ go get -u github.com/panjf2000/gnet

The following companies/organizations use `gnet` as the underlying network service in production.

<a href="https://www.tencent.com"><img src="http://img.taohuawu.club/gallery/tencent_logo.png" width="250" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.iqiyi.com" target="_blank"><img src="http://img.taohuawu.club/gallery/iqiyi-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.mi.com" target="_blank"><img src="http://img.taohuawu.club/gallery/mi-logo.png" width="150" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.360.com" target="_blank"><img src="http://img.taohuawu.club/gallery/360-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://tieba.baidu.com/" target="_blank"><img src="http://img.taohuawu.club/gallery/baidu-tieba-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://game.qq.com/" target="_blank"><img src="http://img.taohuawu.club/gallery/tencent-games-logo.jpeg" width="200" align="middle"/></a>
<a href="https://www.tencent.com"><img src="https://res.strikefreedom.top/static_res/logos/tencent_logo.png" width="250" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.iqiyi.com" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/iqiyi-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.mi.com" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/mi-logo.png" width="150" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.360.com" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/360-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://tieba.baidu.com/" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/baidu-tieba-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://game.qq.com/" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/tencent-games-logo.jpeg" width="200" align="middle"/></a>

If you have `gnet` integrated into projects, feel free to open a pull request refreshing this list.

Expand All @@ -90,6 +90,8 @@ This is the full framework ranking of Go and `gnet` tops all the other framework

To see the full ranking list, visit [TechEmpower Plaintext Benchmark](https://www.techempower.com/benchmarks/#section=test&runid=a07a7117-f861-49b2-a710-94970c5767d0&test=plaintext).

***Note that the HTTP implementation of gnet on TechEmpower is half-baked and fine-tuned for benchmark purposes only and far from production-ready.***

## Contrasts to the similar networking libraries

## On Linux (epoll)
Expand Down
4 changes: 3 additions & 1 deletion README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ go get -u github.com/panjf2000/gnet

以下公司/组织在生产环境上使用了 `gnet` 作为底层网络服务。

<a href="https://www.tencent.com"><img src="http://img.taohuawu.club/gallery/tencent_logo.png" width="250" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.iqiyi.com" target="_blank"><img src="http://img.taohuawu.club/gallery/iqiyi-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.mi.com" target="_blank"><img src="http://img.taohuawu.club/gallery/mi-logo.png" width="150" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.360.com" target="_blank"><img src="http://img.taohuawu.club/gallery/360-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://tieba.baidu.com/" target="_blank"><img src="http://img.taohuawu.club/gallery/baidu-tieba-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://game.qq.com/" target="_blank"><img src="http://img.taohuawu.club/gallery/tencent-games-logo.jpeg" width="200" align="middle"/></a>
<a href="https://www.tencent.com"><img src="https://res.strikefreedom.top/static_res/logos/tencent_logo.png" width="250" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.iqiyi.com" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/iqiyi-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.mi.com" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/mi-logo.png" width="150" align="middle"/></a>&nbsp;&nbsp;<a href="https://www.360.com" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/360-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://tieba.baidu.com/" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/baidu-tieba-logo.png" width="200" align="middle"/></a>&nbsp;&nbsp;<a href="https://game.qq.com/" target="_blank"><img src="https://res.strikefreedom.top/static_res/logos/tencent-games-logo.jpeg" width="200" align="middle"/></a>

如果你的项目也在使用 `gnet`,欢迎给我提 Pull Request 来更新这份列表。

Expand All @@ -90,6 +90,8 @@ go get -u github.com/panjf2000/gnet

完整的排行可以通过 [TechEmpower Plaintext Benchmark](https://www.techempower.com/benchmarks/#section=test&runid=a07a7117-f861-49b2-a710-94970c5767d0&test=plaintext) 查看。

***请注意,TechEmpower 上的 gnet 的 HTTP 实现是不完备且针对性调优的,仅仅是用于压测目的,不是生产可用的***

## 同类型的网络库性能对比

## On Linux (epoll)
Expand Down
106 changes: 105 additions & 1 deletion client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package gnet

import (
"io"
"math/rand"
"net"
"sync"
Expand Down Expand Up @@ -60,7 +61,8 @@ func (ev *clientEvents) OnTraffic(c Conn) (action Action) {
} else { // UDP
ev.packetLen = 1024
}
buf, _ := c.Next(-1)
buf, err := c.Next(-1)
assert.NoError(ev.tester, err)
p = append(p, buf...)
if len(p) < ev.packetLen {
c.SetContext(p)
Expand Down Expand Up @@ -338,6 +340,8 @@ func startGnetClient(t *testing.T, cli *Client, ev *clientEvents, network, addr
}
require.NoError(t, err)
defer c.Close()
err = c.Wake(nil)
require.NoError(t, err)
var rspCh chan []byte
if network == "udp" {
rspCh = make(chan []byte, 1)
Expand Down Expand Up @@ -387,3 +391,103 @@ func startGnetClient(t *testing.T, cli *Client, ev *clientEvents, network, addr
}
}
}

type clientEventsForWake struct {
BuiltinEventEngine
tester *testing.T
ch chan struct{}
}

func (ev *clientEventsForWake) OnBoot(_ Engine) Action {
ev.ch = make(chan struct{})
return None
}

func (ev *clientEventsForWake) OnTraffic(c Conn) (action Action) {
n, err := c.Read(nil)
assert.Zerof(ev.tester, n, "expected: %v, but got: %v", 0, n)
assert.NoErrorf(ev.tester, err, "expected: %v, but got: %v", nil, err)
buf := make([]byte, 10)
n, err = c.Read(buf)
assert.Zerof(ev.tester, n, "expected: %v, but got: %v", 0, n)
assert.ErrorIsf(ev.tester, err, io.ErrShortBuffer, "expected error: %v, but got: %v", io.ErrShortBuffer, err)
buf, err = c.Next(10)
assert.Nilf(ev.tester, buf, "expected: %v, but got: %v", nil, buf)
assert.ErrorIsf(ev.tester, err, io.ErrShortBuffer, "expected error: %v, but got: %v", io.ErrShortBuffer, err)
buf, err = c.Next(-1)
assert.Nilf(ev.tester, buf, "expected: %v, but got: %v", nil, buf)
assert.NoErrorf(ev.tester, err, "expected: %v, but got: %v", nil, err)
buf, err = c.Peek(10)
assert.Nilf(ev.tester, buf, "expected: %v, but got: %v", nil, buf)
assert.ErrorIsf(ev.tester, err, io.ErrShortBuffer, "expected error: %v, but got: %v", io.ErrShortBuffer, err)
buf, err = c.Peek(-1)
assert.Nilf(ev.tester, buf, "expected: %v, but got: %v", nil, buf)
assert.NoErrorf(ev.tester, err, "expected: %v, but got: %v", nil, err)
n, err = c.Discard(10)
assert.Zerof(ev.tester, n, "expected: %v, but got: %v", 0, n)
assert.NoErrorf(ev.tester, err, "expected: %v, but got: %v", nil, err)
n, err = c.Discard(-1)
assert.Zerof(ev.tester, n, "expected: %v, but got: %v", 0, n)
assert.NoErrorf(ev.tester, err, "expected: %v, but got: %v", nil, err)
m, err := c.WriteTo(io.Discard)
assert.Zerof(ev.tester, n, "expected: %v, but got: %v", 0, m)
assert.NoErrorf(ev.tester, err, "expected: %v, but got: %v", nil, err)
n = c.InboundBuffered()
assert.Zerof(ev.tester, n, "expected: %v, but got: %v", 0, m)
<-ev.ch
return None
}

type serverEventsForWake struct {
BuiltinEventEngine
network, addr string
client *Client
clientEV *clientEventsForWake
tester *testing.T
clients int32
started int32
}

func (ev *serverEventsForWake) OnOpen(_ Conn) ([]byte, Action) {
atomic.AddInt32(&ev.clients, 1)
return nil, None
}

func (ev *serverEventsForWake) OnClose(_ Conn, _ error) Action {
if atomic.AddInt32(&ev.clients, -1) == 0 {
return Shutdown
}
return None
}

func (ev *serverEventsForWake) OnTick() (time.Duration, Action) {
if atomic.CompareAndSwapInt32(&ev.started, 0, 1) {
go testConnWakeImmediately(ev.tester, ev.client, ev.clientEV, ev.network, ev.addr)
}
return 100 * time.Millisecond, None
}

func testConnWakeImmediately(t *testing.T, client *Client, clientEV *clientEventsForWake, network, addr string) {
c, err := client.Dial(network, addr)
assert.NoErrorf(t, err, "failed to dial: %v", err)
err = c.Wake(nil)
assert.NoError(t, err)
err = c.Close()
assert.NoError(t, err)
clientEV.ch <- struct{}{}
}

func TestWakeConnImmediately(t *testing.T) {
clientEV := &clientEventsForWake{tester: t}
client, err := NewClient(clientEV, WithLogLevel(logging.DebugLevel))
assert.NoError(t, err)

err = client.Start()
assert.NoError(t, err)
defer client.Stop() //nolint:errcheck

serverEV := &serverEventsForWake{tester: t, network: "tcp", addr: ":18888", client: client, clientEV: clientEV}

err = Run(serverEV, serverEV.network+"://"+serverEV.addr, WithTicker(true))
assert.NoError(t, err)
}
2 changes: 1 addition & 1 deletion connection_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func (c *conn) Read(p []byte) (n int, err error) {
n = copy(p, c.buffer)
c.buffer = c.buffer[n:]
if n == 0 && len(p) > 0 {
err = io.EOF
err = io.ErrShortBuffer
}
return
}
Expand Down
32 changes: 32 additions & 0 deletions connection_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ func (c *conn) resetBuffer() {
}

func (c *conn) Read(p []byte) (n int, err error) {
if c.buffer == nil {
if len(p) == 0 {
return 0, nil
}
return 0, io.ErrShortBuffer
}

if c.inboundBuffer.IsEmpty() {
n = copy(p, c.buffer.B)
c.buffer.B = c.buffer.B[n:]
Expand All @@ -130,6 +137,13 @@ func (c *conn) Read(p []byte) (n int, err error) {
}

func (c *conn) Next(n int) (buf []byte, err error) {
if c.buffer == nil {
if n <= 0 {
return nil, nil
}
return nil, io.ErrShortBuffer
}

inBufferLen := c.inboundBuffer.Buffered()
if totalLen := inBufferLen + c.buffer.Len(); n > totalLen {
return nil, io.ErrShortBuffer
Expand Down Expand Up @@ -160,6 +174,13 @@ func (c *conn) Next(n int) (buf []byte, err error) {
}

func (c *conn) Peek(n int) (buf []byte, err error) {
if c.buffer == nil {
if n <= 0 {
return nil, nil
}
return nil, io.ErrShortBuffer
}

inBufferLen := c.inboundBuffer.Buffered()
if totalLen := inBufferLen + c.buffer.Len(); n > totalLen {
return nil, io.ErrShortBuffer
Expand All @@ -186,6 +207,10 @@ func (c *conn) Peek(n int) (buf []byte, err error) {
}

func (c *conn) Discard(n int) (int, error) {
if c.buffer == nil {
return 0, nil
}

inBufferLen := c.inboundBuffer.Buffered()
tempBufferLen := c.buffer.Len()
if inBufferLen+tempBufferLen < n || n <= 0 {
Expand Down Expand Up @@ -242,6 +267,10 @@ func (c *conn) WriteTo(w io.Writer) (n int64, err error) {
return
}
}

if c.buffer == nil {
return 0, nil
}
defer c.buffer.Reset()
return c.buffer.WriteTo(w)
}
Expand All @@ -251,6 +280,9 @@ func (c *conn) Flush() error {
}

func (c *conn) InboundBuffered() int {
if c.buffer == nil {
return 0
}
return c.inboundBuffer.Buffered() + c.buffer.Len()
}

Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ require (
github.com/stretchr/testify v1.8.4
github.com/valyala/bytebufferpool v1.0.0
go.uber.org/zap v1.21.0
golang.org/x/sync v0.3.0
golang.org/x/sys v0.12.0
golang.org/x/sync v0.5.0
golang.org/x/sys v0.15.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
)

Expand Down
7 changes: 4 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
Expand Down
29 changes: 22 additions & 7 deletions internal/socket/sockopts_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,28 @@ func SetKeepAlivePeriod(fd, secs int) error {
if secs <= 0 {
return errors.New("invalid time duration")
}
if err := os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1)); err != nil {
return err

if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil {
return os.NewSyscallError("setsockopt", err)
}

if err := unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, secs); err != nil {
return os.NewSyscallError("setsockopt", err)
}
switch err := os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, secs)); err {
case nil, unix.ENOPROTOOPT: // OS X 10.7 and earlier don't support this option
default:
return err

interval := secs / 5
if interval == 0 {
interval = 1
}
if err := unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, interval); err != nil {
// In earlier versions, macOS only supported setting TCP_KEEPALIVE (the equivalent of TCP_KEEPIDLE on other platforms),
// but since macOS 10.8 it has supported TCP_KEEPINTVL and TCP_KEEPCNT.
// If the current OS is macOS and the error is ENOPROTOOPT, ignore it.
if err == unix.ENOPROTOOPT {
err = nil
}
return os.NewSyscallError("setsockopt", err)
}
return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, secs))

return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPCNT, 5))
}
24 changes: 24 additions & 0 deletions internal/socket/sockopts_openbsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2024 The Gnet Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package socket

import "golang.org/x/sys/unix"

// SetKeepAlivePeriod sets whether the operating system should send
// keep-alive messages on the connection and sets period between TCP keep-alive probes.
func SetKeepAlivePeriod(_, _ int) error {
// OpenBSD has no user-settable per-socket TCP keepalive options.
return unix.ENOPROTOOPT
}
Loading

0 comments on commit a509c76

Please sign in to comment.