tcp服务器中的IdleTimeout

问题描述 投票:0回答:1

我正在使用Go语言开发一个包含TCP服务器的项目。我试图在服务器套接字上实现空闲超时,但无法做到。我正在使用的Go代码如下:

package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
    "strconv"
    "time"
)

func main() {
    startServer(6666, time.Duration(2)*time.Second)
}

func startServer(port int, deadline time.Duration) {
    // Listen for incoming connections.
    strPort := strconv.Itoa(port)
    l, err := net.Listen("tcp", ":"+strPort)
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        os.Exit(1)
    }
    // Close the listener when the application closes.
    defer l.Close()
    fmt.Println("Listening on port:" + strPort)
    for {
        // Listen for an incoming connection.
        conn, err := l.Accept()
        if err != nil {
            fmt.Println("Error accepting: ", err.Error())
            os.Exit(1)
        }

        fmt.Println("Got new connection")

        // Set read timeout
        conn.SetReadDeadline(time.Now().Add(deadline))

        // Handle connections in a new goroutine.
        go handleRequest(conn)
    }
}

func handleRequest(conn net.Conn) {
    reader := bufio.NewReader(conn)
    scanner := bufio.NewScanner(reader)

    for scanner.Scan() {
        fmt.Println(scanner.Bytes())
    }
}

我希望它超时并在2秒后关闭连接。有人可以告诉我我可能做错了什么。为了测试它,我使用的是我编写为Python scipt的TCP客户端。客户端代码如下:

λ python
Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from socket import *
>>> c = socket(family=AF_INET, type=SOCK_STREAM)
>>> c.connect(('localhost', 6666))

我总是可以跟踪所有打开的连接,以及它们在某种数据结构中的最后活动时间,并启动一个goroutine,定期检查每个连接的时间,关闭我暂时没有听到的连接。但我想利用内置方法SetReadDeadline()来完成这项工作。

go tcp tcpserver
1个回答
3
投票

netSetDeadline包文档中,它指出

   // An idle timeout can be implemented by repeatedly extending
   // the deadline after successful Read or Write calls.

您可以通过创建自己的net.Conn类型来实现您想要超时的调用。由于空闲连接通常在Read中等待,这通常是您想要设置截止日期的地方。

type Conn struct {
    net.Conn
    idleTimeout time.Duration
}

func (c *Conn) Read(b []byte) (int, error) {
    err := c.Conn.SetReadDeadline(time.Now().Add(c.idleTimeout))
    if err != nil {
        return 0, err
    }
    return c.Conn.Read(b)
}
© www.soinside.com 2019 - 2024. All rights reserved.