打开新连接时,我有时会使用封闭式网络连接" client.Socket.Read(message)
函数中的receive
错误。
这很奇怪,但真正奇怪的是,当客户端通过close(connection.Data)
时,我在manager.unregister
处尝试关闭已关闭的频道时出错。< / p>
我在这里明显遗漏了一些东西,因为我的所有记录都表明这些都是全新的未使用的频道和套接字。
有什么想法吗?
我使用Golang版本1.10。
type ClientManager struct {
clients map[*types.Client]bool
broadcast chan []byte
register chan *types.Client
unregister chan *types.Client
}
func CloseSocket(client *types.Client) {
client.M.Lock()
defer client.M.Unlock()
if !client.Closed {
client.Socket.Close()
client.Closed = true
}
}
func (manager *ClientManager) receive(client *types.Client) {
for {
message := make([]byte, 4096)
fmt.Println("client listening:", client)
length, err := client.Socket.Read(message)
if err != nil {
fmt.Println(err)
manager.unregister <- client
CloseSocket(client)
break
}
if length > 0 {
request := util.DecodeGob(message)
HandleRequest(request, client)
}
}
}
func (manager *ClientManager) start() {
fmt.Println("Listening for TCP connections...")
for {
select {
case connection := <-manager.register:
manager.clients[connection] = true
fmt.Println("Added new connection!")
case connection := <-manager.unregister:
if _, ok := manager.clients[connection]; ok {
close(connection.Data)
delete(manager.clients, connection)
fmt.Println("manager.clients:", manager.clients)
fmt.Println("A connection has terminated!")
}
}
}
func Run(port string) {
fmt.Println("Starting server...")
listener, error := net.Listen("tcp", port)
if error != nil {
fmt.Println(error)
}
manager := ClientManager{
clients: make(map[*types.Client]bool),
broadcast: make(chan []byte),
register: make(chan *types.Client),
unregister: make(chan *types.Client),
}
go manager.start()
fmt.Println("Server running on port " + port + "!")
for {
connection, _ := listener.Accept()
if error != nil {
fmt.Println(error)
}
fmt.Println("\nRemote address:", connection.RemoteAddr())
client := &types.Client{Socket: connection, Data: make(chan []byte)}
manager.register <- client
go manager.receive(client)
go manager.send(client)
}
}
记录:
Starting server...
Server running on port :9000!
Listening for TCP connections...
Remote address: [::1]:54857
Added new connection!
client listening: &{0xc42000e528 0xc42007e240 false}
EOF
manager.clients: map[]
A connection has terminated!
Remote address: [::1]:54860
Added new connection!
client listening: &{0xc4200e2000 0xc4200e6000 false}
EOF
manager.clients: map[]
A connection has terminated!
Remote address: [::1]:54863
Added new connection!
client listening: &{0xc420110000 0xc420116000 false}
read tcp [::1]:9000->[::1]:54863: use of closed network connection
panic: close of closed channel
goroutine 5 [running]:
go_gomoku/server.(*ClientManager).start(0xc42000c920)
/Users/themainframe/go/src/go_gomoku/server/server.go:397 +0x35c
created by go_gomoku/server.Run
/Users/themainframe/go/src/go_gomoku/server/server.go:434 +0x242
编辑:将mutex添加到客户端,不再有种族输出。 Bug仍然存在。
答案 0 :(得分:-2)
好的,解决了。我需要为第一次写入通道实现退避,因为有时它在第一次尝试时失败了。现在它优雅地等待片刻并完美连接。这是它的样子:
func SendBackoff(data []byte, client *types.Client, i int) {
select {
case client.Data <- data:
return
default:
time.Sleep(500 * time.Millisecond)
fmt.Println("Trying again!", i)
if (i > 5) {
return
}
SendBackoff(data, client, i + 1)
}
}
func SendToClient(request types.Request, client *types.Client) {
data, err := util.GobToBytes(request)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Trying to send:", data)
SendBackoff(data, client, 1)
}