我正在使用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()
来完成这项工作。
在net
的SetDeadline
包文档中,它指出
// 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)
}