我使用服务器从客户端向所有连接的客户端广播/回显消息。服务器仅广播它收到的第一条消息,尽管它仍然接收到消息-因为fmt.Println([] byte(buf))仍从客户端打印新消息-新客户端可以连接(但它们的消息也不会被连接)广播)。
经过一些反馈后,看起来好像有一个例程被卡住了。但是到目前为止,我一直找不到哪个。非常感谢您的帮助。
服务器:
package main
import (
"crypto/tls"
"encoding/binary"
"fmt"
"io"
"log"
"net"
"net/http"
_ "net/http/pprof"
)
type client chan<- string // an outgoing message channel
var (
entering = make(chan client, 10)
leaving = make(chan client, 10)
messages = make(chan string, 10) // all incoming client messages
)
func broadcaster() {
clients := make(map[client]bool) // all connected clients
for {
select {
case msg := <-messages:
// Broadcast incoming message to all clients' outgoing message channels.
for cli := range clients {
cli <- string(msg)
}
case cli := <-entering:
clients[cli] = true
case cli := <-leaving:
delete(clients, cli)
close(cli)
}
}
}
func handleConn(conn net.Conn) {
ch := make(chan string) // outgoing client messages
go clientWriter(conn, ch)
defer conn.Close()
entering <- ch
buf := make([]byte, 0, 2+64*1024)
for {
n, err := io.ReadFull(conn, buf[:2])
if err != nil {
fmt.Println(n, err)
leaving <- ch
return
}
msgLen := binary.BigEndian.Uint16(buf[0:2])
buf = buf[0 : 2+msgLen]
n, err = io.ReadFull(conn, buf[2:2+msgLen])
if err != nil {
fmt.Println(err)
leaving <- ch
return
}
messages <- string(buf)
fmt.Println([]byte(buf))
}
}
func clientWriter(conn net.Conn, ch <-chan string) {
for msg := range ch {
_, err := fmt.Fprintln(conn, msg)
if err != nil {
fmt.Println(err)
}
}
}
func main() {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
cer, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
log.Println(err)
return
}
config := &tls.Config{
Certificates: []tls.Certificate{cer},
// Reject any TLS certificate that cannot be validated
//ClientAuth: tls.RequireAndVerifyClientCert,
// PFS, this will reject client with RSA certificates
CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
// Force it server side
PreferServerCipherSuites: true,
// TLS 1.2
MinVersion: tls.VersionTLS12}
listener, err := tls.Listen("tcp", "localhost:443", config)
if err != nil {
log.Fatal(err)
}
go broadcaster()
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
go handleConn(conn)
}
}
我最好的猜测是消息通道卡住了-但是我无法确定在哪里。非常感谢您的帮助。
客户端发送[]个字节,其字节数为[0,加密消息长度,加密消息],例如[0 52 155 84 146 8 228 90 28 41 88 33 178 143 243 243 160 160 255 180 73 20 43 129 155 132 255 207 10 9 130 54 216 44 38 141 101 17 125 101 4 62 228 221 158 196 41 163 227 253 71179172143225]
更新1: 抱歉,我的调试技巧不佳。这是完整的goroutine堆栈转储(有效和无效)。在我看来,区别在于goroutine 8是“可运行的”,而goroutine 9是带有“ runtime_pollWait”的“ IO等待”。有任何解决方法的想法吗?
服务器启动后: 没有来自客户端的任何事先输入(连接除外)。在这种状态下,广播将运行一次。
goroutine 12 [running]:
runtime/pprof.writeGoroutineStacks(0x7da840, 0xc42035e0e0, 0x411a69, 0xc420150570)
/usr/lib/go-1.10/src/runtime/pprof/pprof.go:650 +0xa7
runtime/pprof.writeGoroutine(0x7da840, 0xc42035e0e0, 0x2, 0xc42006c000, 0x7da640)
/usr/lib/go-1.10/src/runtime/pprof/pprof.go:639 +0x44
runtime/pprof.(*Profile).WriteTo(0x980840, 0x7da840, 0xc42035e0e0, 0x2, 0xc42035e0e0, 0x7998f5)
/usr/lib/go-1.10/src/runtime/pprof/pprof.go:310 +0x3e4
net/http/pprof.handler.ServeHTTP(0xc42001a0a1, 0x9, 0x7dd620, 0xc42035e0e0, 0xc420254200)
/usr/lib/go-1.10/src/net/http/pprof/pprof.go:243 +0x20d
net/http/pprof.Index(0x7dd620, 0xc42035e0e0, 0xc420254200)
/usr/lib/go-1.10/src/net/http/pprof/pprof.go:254 +0x1d1
net/http.HandlerFunc.ServeHTTP(0x7b02a8, 0x7dd620, 0xc42035e0e0, 0xc420254200)
/usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
net/http.(*ServeMux).ServeHTTP(0x98dda0, 0x7dd620, 0xc42035e0e0, 0xc420254200)
/usr/lib/go-1.10/src/net/http/server.go:2337 +0x130
net/http.serverHandler.ServeHTTP(0xc42016c000, 0x7dd620, 0xc42035e0e0, 0xc420254200)
/usr/lib/go-1.10/src/net/http/server.go:2694 +0xbc
net/http.(*conn).serve(0xc4201640a0, 0x7dd8e0, 0xc42014c300)
/usr/lib/go-1.10/src/net/http/server.go:1830 +0x651
created by net/http.(*Server).Serve
/usr/lib/go-1.10/src/net/http/server.go:2795 +0x27b
goroutine 1 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8e30, 0x72, 0x0)
/usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc4201b0118, 0x72, 0xc4200a2000, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc4201b0118, 0xffffffffffffff00, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc4201b0100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_unix.go:372 +0x1a8
net.(*netFD).accept(0xc4201b0100, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc42000e018, 0x4122b8, 0x380, 0x78f260)
/usr/lib/go-1.10/src/net/tcpsock_posix.go:136 +0x2e
net.(*TCPListener).Accept(0xc42000e018, 0x4356c4, 0xc420181da0, 0x457610, 0xc420181de0)
/usr/lib/go-1.10/src/net/tcpsock.go:259 +0x49
crypto/tls.(*listener).Accept(0xc42010cd80, 0x7afee0, 0x7ded20, 0xc4200e6000, 0x0)
/usr/lib/go-1.10/src/crypto/tls/tls.go:52 +0x37
main.main()
/home/hendrik/Dropbox/go/chat/server/server.go:109 +0x2ca
goroutine 20 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8d60, 0x72, 0xc42020baa8)
/usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc42015c098, 0x72, 0xffffffffffffff00, 0x7db3a0, 0x9515e0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc42015c098, 0xc4200d6400, 0x400, 0x400)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Read(0xc42015c080, 0xc4200d6400, 0x400, 0x400, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_unix.go:157 +0x17d
net.(*netFD).Read(0xc42015c080, 0xc4200d6400, 0x400, 0x400, 0x57515a, 0xc42015c080, 0xc420202180)
/usr/lib/go-1.10/src/net/fd_unix.go:202 +0x4f
net.(*conn).Read(0xc420156020, 0xc4200d6400, 0x400, 0x400, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/net/net.go:176 +0x6a
crypto/tls.(*block).readFromUntil(0xc420150330, 0x7f84564feae0, 0xc420156020, 0x5, 0xc420156020, 0x5d626a)
/usr/lib/go-1.10/src/crypto/tls/conn.go:493 +0x96
crypto/tls.(*Conn).readRecord(0xc4200e6000, 0x7b0717, 0xc4200e6120, 0x98b7c0)
/usr/lib/go-1.10/src/crypto/tls/conn.go:595 +0xe0
crypto/tls.(*Conn).Read(0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/crypto/tls/conn.go:1156 +0x100
io.ReadAtLeast(0x7f84564feac0, 0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x2, 0x786f60, 0x6d8e00, 0x7f84564feac0)
/usr/lib/go-1.10/src/io/io.go:309 +0x86
io.ReadFull(0x7f84564feac0, 0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x10002, 0x6863ee, 0x1)
/usr/lib/go-1.10/src/io/io.go:327 +0x58
main.handleConn(0x7ded20, 0xc4200e6000)
/home/hendrik/Dropbox/go/chat/server/server.go:52 +0x27d
created by main.main
/home/hendrik/Dropbox/go/chat/server/server.go:115 +0x350
goroutine 4 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8f00, 0x72, 0x0)
/usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc4201b0098, 0x72, 0xc42014c000, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc4201b0098, 0xffffffffffffff00, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc4201b0080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_unix.go:372 +0x1a8
net.(*netFD).accept(0xc4201b0080, 0xc420164120, 0xc42003edf0, 0x402b98)
/usr/lib/go-1.10/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc420156048, 0xc42003ee20, 0x401af7, 0xc420164120)
/usr/lib/go-1.10/src/net/tcpsock_posix.go:136 +0x2e
net.(*TCPListener).AcceptTCP(0xc420156048, 0xc42003ee68, 0xc42003ee70, 0x18)
/usr/lib/go-1.10/src/net/tcpsock.go:246 +0x49
net/http.tcpKeepAliveListener.Accept(0xc420156048, 0x7b00a8, 0xc4201640a0, 0x7dd9a0, 0xc420150750)
/usr/lib/go-1.10/src/net/http/server.go:3216 +0x2f
net/http.(*Server).Serve(0xc42016c000, 0x7dd820, 0xc420156048, 0x0, 0x0)
/usr/lib/go-1.10/src/net/http/server.go:2770 +0x1a5
net/http.(*Server).ListenAndServe(0xc42016c000, 0xc42016c000, 0x0)
/usr/lib/go-1.10/src/net/http/server.go:2711 +0xa9
net/http.ListenAndServe(0x79a39f, 0xe, 0x0, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/net/http/server.go:2969 +0x7a
main.main.func1()
/home/hendrik/Dropbox/go/chat/server/server.go:83 +0x3e
created by main.main
/home/hendrik/Dropbox/go/chat/server/server.go:82 +0x4a
goroutine 36 [runnable]:
net/http.(*connReader).backgroundRead(0xc4201508d0)
/usr/lib/go-1.10/src/net/http/server.go:667
created by net/http.(*connReader).startBackgroundRead
/usr/lib/go-1.10/src/net/http/server.go:664 +0xce
goroutine 11 [select]:
main.broadcaster()
/home/hendrik/Dropbox/go/chat/server/server.go:25 +0x193
created by main.main
/home/hendrik/Dropbox/go/chat/server/server.go:107 +0x2b0
goroutine 21 [chan receive]:
main.clientWriter(0x7ded20, 0xc4200e6000, 0xc42007a120)
/home/hendrik/Dropbox/go/chat/server/server.go:73 +0x52
created by main.handleConn
/home/hendrik/Dropbox/go/chat/server/server.go:46 +0x89
播完一遍后(无法播放) 这是一个广播之后的状态。服务器将不再广播任何消息。
goroutine 12 [running]:
runtime/pprof.writeGoroutineStacks(0x7da840, 0xc42035e1c0, 0x411a69, 0xc4201507e0)
/usr/lib/go-1.10/src/runtime/pprof/pprof.go:650 +0xa7
runtime/pprof.writeGoroutine(0x7da840, 0xc42035e1c0, 0x2, 0xc420468000, 0x7da640)
/usr/lib/go-1.10/src/runtime/pprof/pprof.go:639 +0x44
runtime/pprof.(*Profile).WriteTo(0x980840, 0x7da840, 0xc42035e1c0, 0x2, 0xc42035e1c0, 0x7998f5)
/usr/lib/go-1.10/src/runtime/pprof/pprof.go:310 +0x3e4
net/http/pprof.handler.ServeHTTP(0xc42001a2e1, 0x9, 0x7dd620, 0xc42035e1c0, 0xc420146100)
/usr/lib/go-1.10/src/net/http/pprof/pprof.go:243 +0x20d
net/http/pprof.Index(0x7dd620, 0xc42035e1c0, 0xc420146100)
/usr/lib/go-1.10/src/net/http/pprof/pprof.go:254 +0x1d1
net/http.HandlerFunc.ServeHTTP(0x7b02a8, 0x7dd620, 0xc42035e1c0, 0xc420146100)
/usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
net/http.(*ServeMux).ServeHTTP(0x98dda0, 0x7dd620, 0xc42035e1c0, 0xc420146100)
/usr/lib/go-1.10/src/net/http/server.go:2337 +0x130
net/http.serverHandler.ServeHTTP(0xc42016c000, 0x7dd620, 0xc42035e1c0, 0xc420146100)
/usr/lib/go-1.10/src/net/http/server.go:2694 +0xbc
net/http.(*conn).serve(0xc4201640a0, 0x7dd8e0, 0xc42014c300)
/usr/lib/go-1.10/src/net/http/server.go:1830 +0x651
created by net/http.(*Server).Serve
/usr/lib/go-1.10/src/net/http/server.go:2795 +0x27b
goroutine 1 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8e30, 0x72, 0x0)
/usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc4201b0118, 0x72, 0xc4200a2000, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc4201b0118, 0xffffffffffffff00, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc4201b0100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_unix.go:372 +0x1a8
net.(*netFD).accept(0xc4201b0100, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc42000e018, 0x4122b8, 0x380, 0x78f260)
/usr/lib/go-1.10/src/net/tcpsock_posix.go:136 +0x2e
net.(*TCPListener).Accept(0xc42000e018, 0x4356c4, 0xc420181da0, 0x457610, 0xc420181de0)
/usr/lib/go-1.10/src/net/tcpsock.go:259 +0x49
crypto/tls.(*listener).Accept(0xc42010cd80, 0x7afee0, 0x7ded20, 0xc4200e6000, 0x0)
/usr/lib/go-1.10/src/crypto/tls/tls.go:52 +0x37
main.main()
/home/hendrik/Dropbox/go/chat/server/server.go:109 +0x2ca
goroutine 20 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8d60, 0x72, 0xc42020baa8)
/usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc42015c098, 0x72, 0xffffffffffffff00, 0x7db3a0, 0x9515e0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc42015c098, 0xc4200d6400, 0x400, 0x400)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Read(0xc42015c080, 0xc4200d6400, 0x400, 0x400, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_unix.go:157 +0x17d
net.(*netFD).Read(0xc42015c080, 0xc4200d6400, 0x400, 0x400, 0x2, 0x80, 0x82)
/usr/lib/go-1.10/src/net/fd_unix.go:202 +0x4f
net.(*conn).Read(0xc420156020, 0xc4200d6400, 0x400, 0x400, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/net/net.go:176 +0x6a
crypto/tls.(*block).readFromUntil(0xc420150330, 0x7f84564feae0, 0xc420156020, 0x5, 0xc420156020, 0x1)
/usr/lib/go-1.10/src/crypto/tls/conn.go:493 +0x96
crypto/tls.(*Conn).readRecord(0xc4200e6000, 0x7b0717, 0xc4200e6120, 0x0)
/usr/lib/go-1.10/src/crypto/tls/conn.go:595 +0xe0
crypto/tls.(*Conn).Read(0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/crypto/tls/conn.go:1156 +0x100
io.ReadAtLeast(0x7f84564feac0, 0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x2, 0x786f60, 0x0, 0x7f84564feac0)
/usr/lib/go-1.10/src/io/io.go:309 +0x86
io.ReadFull(0x7f84564feac0, 0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/io/io.go:327 +0x58
main.handleConn(0x7ded20, 0xc4200e6000)
/home/hendrik/Dropbox/go/chat/server/server.go:52 +0x27d
created by main.main
/home/hendrik/Dropbox/go/chat/server/server.go:115 +0x350
goroutine 4 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8f00, 0x72, 0x0)
/usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc4201b0098, 0x72, 0xc42014c000, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc4201b0098, 0xffffffffffffff00, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc4201b0080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/internal/poll/fd_unix.go:372 +0x1a8
net.(*netFD).accept(0xc4201b0080, 0xc420164120, 0xc42003edf0, 0x402b98)
/usr/lib/go-1.10/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc420156048, 0xc42003ee20, 0x401af7, 0xc420164120)
/usr/lib/go-1.10/src/net/tcpsock_posix.go:136 +0x2e
net.(*TCPListener).AcceptTCP(0xc420156048, 0xc42003ee68, 0xc42003ee70, 0x18)
/usr/lib/go-1.10/src/net/tcpsock.go:246 +0x49
net/http.tcpKeepAliveListener.Accept(0xc420156048, 0x7b00a8, 0xc4201640a0, 0x7dd9a0, 0xc420150750)
/usr/lib/go-1.10/src/net/http/server.go:3216 +0x2f
net/http.(*Server).Serve(0xc42016c000, 0x7dd820, 0xc420156048, 0x0, 0x0)
/usr/lib/go-1.10/src/net/http/server.go:2770 +0x1a5
net/http.(*Server).ListenAndServe(0xc42016c000, 0xc42016c000, 0x0)
/usr/lib/go-1.10/src/net/http/server.go:2711 +0xa9
net/http.ListenAndServe(0x79a39f, 0xe, 0x0, 0x0, 0x0, 0x0)
/usr/lib/go-1.10/src/net/http/server.go:2969 +0x7a
main.main.func1()
/home/hendrik/Dropbox/go/chat/server/server.go:83 +0x3e
created by main.main
/home/hendrik/Dropbox/go/chat/server/server.go:82 +0x4a
goroutine 37 [runnable]:
net/http.(*connReader).backgroundRead(0xc4201508d0)
/usr/lib/go-1.10/src/net/http/server.go:667
created by net/http.(*connReader).startBackgroundRead
/usr/lib/go-1.10/src/net/http/server.go:664 +0xce
goroutine 11 [select]:
main.broadcaster()
/home/hendrik/Dropbox/go/chat/server/server.go:25 +0x193
created by main.main
/home/hendrik/Dropbox/go/chat/server/server.go:107 +0x2b0
goroutine 21 [chan receive]:
main.clientWriter(0x7ded20, 0xc4200e6000, 0xc42007a120)
/home/hendrik/Dropbox/go/chat/server/server.go:73 +0x52
created by main.handleConn
/home/hendrik/Dropbox/go/chat/server/server.go:46 +0x89
goroutine个人资料:总共7个-在收到任何消息之前
1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d7e5d 0x563dcf 0x574eda 0x5c5096 0x5c55a0 0x5c8b40 0x471196 0x471308 0x6d907d 0x45ab71
# 0x428ae6 internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
# 0x4d6f7a internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
# 0x4d6ffc internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
# 0x4d7e5c internal/poll.(*FD).Read+0x17c /usr/lib/go-1.10/src/internal/poll/fd_unix.go:157
# 0x563dce net.(*netFD).Read+0x4e /usr/lib/go-1.10/src/net/fd_unix.go:202
# 0x574ed9 net.(*conn).Read+0x69 /usr/lib/go-1.10/src/net/net.go:176
# 0x5c5095 crypto/tls.(*block).readFromUntil+0x95 /usr/lib/go-1.10/src/crypto/tls/conn.go:493
# 0x5c559f crypto/tls.(*Conn).readRecord+0xdf /usr/lib/go-1.10/src/crypto/tls/conn.go:595
# 0x5c8b3f crypto/tls.(*Conn).Read+0xff /usr/lib/go-1.10/src/crypto/tls/conn.go:1156
# 0x471195 io.ReadAtLeast+0x85 /usr/lib/go-1.10/src/io/io.go:309
# 0x471307 io.ReadFull+0x57 /usr/lib/go-1.10/src/io/io.go:327
# 0x6d907c main.handleConn+0x27c /home/hendrik/Dropbox/go/chat/server/server.go:52
1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d93f8 0x5646e2 0x57e85e 0x57ce39 0x66271f 0x6614b5 0x661209 0x66224a 0x6d98ae 0x45ab71
# 0x428ae6 internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
# 0x4d6f7a internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
# 0x4d6ffc internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
# 0x4d93f7 internal/poll.(*FD).Accept+0x1a7 /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372
# 0x5646e1 net.(*netFD).accept+0x41 /usr/lib/go-1.10/src/net/fd_unix.go:238
# 0x57e85d net.(*TCPListener).accept+0x2d /usr/lib/go-1.10/src/net/tcpsock_posix.go:136
# 0x57ce38 net.(*TCPListener).AcceptTCP+0x48 /usr/lib/go-1.10/src/net/tcpsock.go:246
# 0x66271e net/http.tcpKeepAliveListener.Accept+0x2e /usr/lib/go-1.10/src/net/http/server.go:3216
# 0x6614b4 net/http.(*Server).Serve+0x1a4 /usr/lib/go-1.10/src/net/http/server.go:2770
# 0x661208 net/http.(*Server).ListenAndServe+0xa8 /usr/lib/go-1.10/src/net/http/server.go:2711
# 0x662249 net/http.ListenAndServe+0x79 /usr/lib/go-1.10/src/net/http/server.go:2969
# 0x6d98ad main.main.func1+0x3d /home/hendrik/Dropbox/go/chat/server/server.go:83
1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d93f8 0x5646e2 0x57e85e 0x57d049 0x5e2bd7 0x6d973a 0x42dcf2 0x45ab71
# 0x428ae6 internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
# 0x4d6f7a internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
# 0x4d6ffc internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
# 0x4d93f7 internal/poll.(*FD).Accept+0x1a7 /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372
# 0x5646e1 net.(*netFD).accept+0x41 /usr/lib/go-1.10/src/net/fd_unix.go:238
# 0x57e85d net.(*TCPListener).accept+0x2d /usr/lib/go-1.10/src/net/tcpsock_posix.go:136
# 0x57d048 net.(*TCPListener).Accept+0x48 /usr/lib/go-1.10/src/net/tcpsock.go:259
# 0x5e2bd6 crypto/tls.(*listener).Accept+0x36 /usr/lib/go-1.10/src/crypto/tls/tls.go:52
# 0x6d9739 main.main+0x2c9 /home/hendrik/Dropbox/go/chat/server/server.go:109
# 0x42dcf1 runtime.main+0x211 /usr/lib/go-1.10/src/runtime/proc.go:198
1 @ 0x42e14a 0x42e1fe 0x405f92 0x405c8b 0x6d9342 0x45ab71
# 0x6d9341 main.clientWriter+0x51 /home/hendrik/Dropbox/go/chat/server/server.go:73
1 @ 0x42e14a 0x43db50 0x6d8cb3 0x45ab71
# 0x6d8cb2 main.broadcaster+0x192 /home/hendrik/Dropbox/go/chat/server/server.go:25
1 @ 0x657e40 0x45ab71
# 0x657e40 net/http.(*connReader).backgroundRead+0x0 /usr/lib/go-1.10/src/net/http/server.go:667
1 @ 0x6d0408 0x6d0210 0x6ccd54 0x6d851d 0x6d88a1 0x65e444 0x6600b0 0x6610ec 0x65d461 0x45ab71
# 0x6d0407 runtime/pprof.writeRuntimeProfile+0x97 /usr/lib/go-1.10/src/runtime/pprof/pprof.go:679
# 0x6d020f runtime/pprof.writeGoroutine+0x9f /usr/lib/go-1.10/src/runtime/pprof/pprof.go:641
# 0x6ccd53 runtime/pprof.(*Profile).WriteTo+0x3e3 /usr/lib/go-1.10/src/runtime/pprof/pprof.go:310
# 0x6d851c net/http/pprof.handler.ServeHTTP+0x20c /usr/lib/go-1.10/src/net/http/pprof/pprof.go:243
# 0x6d88a0 net/http/pprof.Index+0x1d0 /usr/lib/go-1.10/src/net/http/pprof/pprof.go:254
# 0x65e443 net/http.HandlerFunc.ServeHTTP+0x43 /usr/lib/go-1.10/src/net/http/server.go:1947
# 0x6600af net/http.(*ServeMux).ServeHTTP+0x12f /usr/lib/go-1.10/src/net/http/server.go:2337
# 0x6610eb net/http.serverHandler.ServeHTTP+0xbb /usr/lib/go-1.10/src/net/http/server.go:2694
# 0x65d460 net/http.(*conn).serve+0x650 /usr/lib/go-1.10/src/net/http/server.go:1830
goroutine个人资料:总共7个-首次播放后-不再播放
1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d7e5d 0x563dcf 0x574eda 0x5c5096 0x5c55a0 0x5c8b40 0x471196 0x471308 0x6d907d 0x45ab71
# 0x428ae6 internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
# 0x4d6f7a internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
# 0x4d6ffc internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
# 0x4d7e5c internal/poll.(*FD).Read+0x17c /usr/lib/go-1.10/src/internal/poll/fd_unix.go:157
# 0x563dce net.(*netFD).Read+0x4e /usr/lib/go-1.10/src/net/fd_unix.go:202
# 0x574ed9 net.(*conn).Read+0x69 /usr/lib/go-1.10/src/net/net.go:176
# 0x5c5095 crypto/tls.(*block).readFromUntil+0x95 /usr/lib/go-1.10/src/crypto/tls/conn.go:493
# 0x5c559f crypto/tls.(*Conn).readRecord+0xdf /usr/lib/go-1.10/src/crypto/tls/conn.go:595
# 0x5c8b3f crypto/tls.(*Conn).Read+0xff /usr/lib/go-1.10/src/crypto/tls/conn.go:1156
# 0x471195 io.ReadAtLeast+0x85 /usr/lib/go-1.10/src/io/io.go:309
# 0x471307 io.ReadFull+0x57 /usr/lib/go-1.10/src/io/io.go:327
# 0x6d907c main.handleConn+0x27c /home/hendrik/Dropbox/go/chat/server/server.go:52
1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d93f8 0x5646e2 0x57e85e 0x57ce39 0x66271f 0x6614b5 0x661209 0x66224a 0x6d98ae 0x45ab71
# 0x428ae6 internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
# 0x4d6f7a internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
# 0x4d6ffc internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
# 0x4d93f7 internal/poll.(*FD).Accept+0x1a7 /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372
# 0x5646e1 net.(*netFD).accept+0x41 /usr/lib/go-1.10/src/net/fd_unix.go:238
# 0x57e85d net.(*TCPListener).accept+0x2d /usr/lib/go-1.10/src/net/tcpsock_posix.go:136
# 0x57ce38 net.(*TCPListener).AcceptTCP+0x48 /usr/lib/go-1.10/src/net/tcpsock.go:246
# 0x66271e net/http.tcpKeepAliveListener.Accept+0x2e /usr/lib/go-1.10/src/net/http/server.go:3216
# 0x6614b4 net/http.(*Server).Serve+0x1a4 /usr/lib/go-1.10/src/net/http/server.go:2770
# 0x661208 net/http.(*Server).ListenAndServe+0xa8 /usr/lib/go-1.10/src/net/http/server.go:2711
# 0x662249 net/http.ListenAndServe+0x79 /usr/lib/go-1.10/src/net/http/server.go:2969
# 0x6d98ad main.main.func1+0x3d /home/hendrik/Dropbox/go/chat/server/server.go:83
1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d93f8 0x5646e2 0x57e85e 0x57d049 0x5e2bd7 0x6d973a 0x42dcf2 0x45ab71
# 0x428ae6 internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
# 0x4d6f7a internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
# 0x4d6ffc internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
# 0x4d93f7 internal/poll.(*FD).Accept+0x1a7 /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372
# 0x5646e1 net.(*netFD).accept+0x41 /usr/lib/go-1.10/src/net/fd_unix.go:238
# 0x57e85d net.(*TCPListener).accept+0x2d /usr/lib/go-1.10/src/net/tcpsock_posix.go:136
# 0x57d048 net.(*TCPListener).Accept+0x48 /usr/lib/go-1.10/src/net/tcpsock.go:259
# 0x5e2bd6 crypto/tls.(*listener).Accept+0x36 /usr/lib/go-1.10/src/crypto/tls/tls.go:52
# 0x6d9739 main.main+0x2c9 /home/hendrik/Dropbox/go/chat/server/server.go:109
# 0x42dcf1 runtime.main+0x211 /usr/lib/go-1.10/src/runtime/proc.go:198
1 @ 0x42e14a 0x42e1fe 0x405f92 0x405c8b 0x6d9342 0x45ab71
# 0x6d9341 main.clientWriter+0x51 /home/hendrik/Dropbox/go/chat/server/server.go:73
1 @ 0x42e14a 0x43db50 0x6d8cb3 0x45ab71
# 0x6d8cb2 main.broadcaster+0x192 /home/hendrik/Dropbox/go/chat/server/server.go:25
1 @ 0x4c3195 0x4c10df 0x4bfa29 0x4d7df8 0x563dcf 0x574eda 0x657e9a 0x45ab71
# 0x4c3194 syscall.Syscall+0x4 /usr/lib/go-1.10/src/syscall/asm_linux_amd64.s:18
# 0x4c10de syscall.read+0x5e /usr/lib/go-1.10/src/syscall/zsyscall_linux_amd64.go:749
# 0x4bfa28 syscall.Read+0x48 /usr/lib/go-1.10/src/syscall/syscall_unix.go:162
# 0x4d7df7 internal/poll.(*FD).Read+0x117 /usr/lib/go-1.10/src/internal/poll/fd_unix.go:153
# 0x563dce net.(*netFD).Read+0x4e /usr/lib/go-1.10/src/net/fd_unix.go:202
# 0x574ed9 net.(*conn).Read+0x69 /usr/lib/go-1.10/src/net/net.go:176
# 0x657e99 net/http.(*connReader).backgroundRead+0x59 /usr/lib/go-1.10/src/net/http/server.go:668
1 @ 0x6d0408 0x6d0210 0x6ccd54 0x6d851d 0x6d88a1 0x65e444 0x6600b0 0x6610ec 0x65d461 0x45ab71
# 0x6d0407 runtime/pprof.writeRuntimeProfile+0x97 /usr/lib/go-1.10/src/runtime/pprof/pprof.go:679
# 0x6d020f runtime/pprof.writeGoroutine+0x9f /usr/lib/go-1.10/src/runtime/pprof/pprof.go:641
# 0x6ccd53 runtime/pprof.(*Profile).WriteTo+0x3e3 /usr/lib/go-1.10/src/runtime/pprof/pprof.go:310
# 0x6d851c net/http/pprof.handler.ServeHTTP+0x20c /usr/lib/go-1.10/src/net/http/pprof/pprof.go:243
# 0x6d88a0 net/http/pprof.Index+0x1d0 /usr/lib/go-1.10/src/net/http/pprof/pprof.go:254
# 0x65e443 net/http.HandlerFunc.ServeHTTP+0x43 /usr/lib/go-1.10/src/net/http/server.go:1947
# 0x6600af net/http.(*ServeMux).ServeHTTP+0x12f /usr/lib/go-1.10/src/net/http/server.go:2337
# 0x6610eb net/http.serverHandler.ServeHTTP+0xbb /usr/lib/go-1.10/src/net/http/server.go:2694
# 0x65d460 net/http.(*conn).serve+0x650 /usr/lib/go-1.10/src/net/http/server.go:1830
答案 0 :(得分:0)
仅对您的代码添加一些注释。您将必须测试是否可以解决问题:
在for循环中添加一个延迟决不是一个好主意。将延迟动作移至handleConn
函数中:
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
defer conn.Close() // Not good!
go handleConn(conn)
}
接下来,我将使用传出通道并使其成为缓冲通道:
ch := make(chan string, 10) // outgoing client messages
这有2种效果:
尽管我假设entering
和leaving
不需要,但也可以对所有其他渠道进行相同操作。
编辑:
写入连接时缺少一些错误检查。也许那里出了问题:
func clientWriter(conn net.Conn, ch <-chan string) {
for msg := range ch {
fmt.Fprintln(conn, msg) // add error checking here
}
}
编辑2:
在客户端中安装net/http/pprof服务器,并检查其开始的Web服务器的堆端点,以查看goroutine在哪里挂起。
。