我正在尝试在Windows 10上的Go(go1.8.3 windows / amd64)中实现一个简单的echo服务器,但是在从客户端获取连接(连接到ncat)之后,我发生了这种奇怪的恐慌。我可以发送和接收消息,但无论我做什么,它都会在一段时间后崩溃,我不知道为什么。
代码是
package main
import (
"bufio"
"log"
"net"
)
func echo(conn net.Conn, c chan int) {
c <- 1
reader := bufio.NewReader(conn)
msg, err := reader.ReadBytes('\n')
if err != nil {
log.Printf("error reading from the reader: %v", err)
return
}
conn.Write(msg)
}
func handleConnection(conn net.Conn) {
log.Print("Got connection from: ", conn.RemoteAddr())
conn.Write([]byte("Hello, this is a Go echo server\n"))
c := make(chan int)
for {
go echo(conn, c)
<-c
}
}
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:3000")
if err != nil {
log.Fatalf("couldn't create a tcp server: %v", err)
}
for {
conn, err := listener.Accept()
defer conn.Close()
if err != nil {
log.Printf("couldn't create a connection: %v", err)
return
}
go handleConnection(conn)
}
}
错误是
panic: net: inconsistent fdMutex
goroutine 1048589 [running]:
net.(*fdMutex).rwlock(0xc0420741c0, 0x1, 0x0)
C:/Go/src/net/fd_mutex.go:145 +0x1ab
net.(*netFD).readLock(0xc0420741c0, 0x0, 0x0)
C:/Go/src/net/fd_mutex.go:218 +0x39
net.(*netFD).Read(0xc0420741c0, 0xc365329000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
C:/Go/src/net/fd_windows.go:444 +0x5d
net.(*conn).Read(0xc04205e030, 0xc365329000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
C:/Go/src/net/net.go:181 +0x77
bufio.(*Reader).fill(0xc36532bf08)
C:/Go/src/bufio/bufio.go:97 +0x11e
bufio.(*Reader).ReadSlice(0xc36532bf08, 0xc36532be0a, 0xc36532be00, 0x0, 0x100000000000000, 0x0, 0x1000)
C:/Go/src/bufio/bufio.go:338 +0xc2
bufio.(*Reader).ReadBytes(0xc36532bf08, 0x100a, 0x1000, 0xc365329000, 0x1000, 0x1000, 0x0)
C:/Go/src/bufio/bufio.go:416 +0x6d
main.echo(0x574ce0, 0xc04205e030, 0xc042098d80)
C:/Users/fcfn/goecho/server.go:13 +0x10b
created by main.handleConnection
C:/Users/fcfn/goecho/server.go:27 +0x271
答案 0 :(得分:1)
感谢@JimB,我更了解问题的本质。这是他说的话:
实际错误是因为您从无限数量的goroutine中调用Read。网络包假设没有理由在网上拥有超过1&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; - JimB
这里有一些不好的代码,这对于手头的问题并不是很好。我删除了它,所以它不会误导任何人,正如JimB所建议的那样。
我从JimB那里学到了什么:
echo
函数不应该是goroutine,因为read是一个阻塞操作,我们无法对连接做任何事情,直到我们理解了客户端发送给我们,因此不需要并发;另一方面,handleConnection
在goroutine中运行,因为它应该同时处理多个连接。)