我正在尝试实现非阻塞Accept()
,我到目前为止最好的是以下代码片段(它是一个正在运行的Go v1.6.2程序):
package main
import (
"net"
"log"
"time"
)
func createClient() {
tcpConn, err := net.DialTCP("tcp4", nil, &net.TCPAddr{
IP: net.IPv4(127, 0, 0, 1),
Port: 12819,
})
if err != nil {
log.Fatalln("Error connecting to the server!")
}
log.Println("Managed to dial!")
tcpConn.Close()
}
func main() {
go createClient()
l, err := net.ListenTCP("tcp4", &net.TCPAddr{
IP: net.IPv4(127, 0, 0, 1),
Port: 12819,
})
if err != nil {
log.Fatalln("Can't listen on provided IP/port!")
}
defer l.Close()
if err = l.SetDeadline(time.Now().Add(time.Nanosecond)); err != nil {
log.Fatalln("Can't set appropriate deadline!")
}
tcpConn, err := l.AcceptTCP()
if err != nil {
if opError, ok := err.(*net.OpError); ok && opError.Timeout() {
log.Fatalln("Timeout error!")
}
log.Fatalln("Error while accepting connection!")
}
log.Println("Accepted new connection!")
tcpConn.Close()
}
问题是我总是得到Timeout error!
。据我所知,这是因为当听众的AcceptTCP()
被调用时,之前设定的截止日期已经过期。尝试将其更改为time.Microsecond
,您可能会得到相同的结果(除非您的CPU比我的慢)。只有在截止日期至少为time.Second
时,事情才会开始改变。那是我开始获得Accepted new connection!
/ Managed to dial!
。
所以我认为我已经解决了这个问题。有什么想法吗?
答案 0 :(得分:0)
接受应该是阻止的。您不希望在listen / Accept上设置截止日期,因为您希望它永久地侦听新连接。
你需要把accept放在一个循环中,基本上启动一个新的go例程来处理连接并返回等待新的客户端连接(Accept)。
以下是Go中的典型服务器:
package main
import (
"fmt"
"log"
"net"
"os"
)
func main() {
l, err := net.Listen("tcp", "localhost:12819")
if err != nil {
log.Fatalln("Can't listen on provided IP/port!")
}
defer l.Close()
for {
// Listen for an incoming connection.
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err.Error())
os.Exit(1)
}
// Handle connections in a new goroutine.
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
buf := make([]byte, 1024)
if _, err := conn.Read(buf); err != nil {
fmt.Println("Error reading:", err.Error())
}
conn.Write([]byte("Message received."))
conn.Close()
}
您可以使用shell中的以下命令连接它:
telnet localhost 12819
输入命令,您的请求将被处理和处理。
如您所见,accept命令旨在故意阻止。服务器上的SetDeadline通常在处理阶段进一步完成,以便在读取来自客户端的数据时超时。