Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Goroutines:广播员在收到第一条消息后停止工作_Go_Server_Broadcast_Channel_Goroutine - Fatal编程技术网

Goroutines:广播员在收到第一条消息后停止工作

Goroutines:广播员在收到第一条消息后停止工作,go,server,broadcast,channel,goroutine,Go,Server,Broadcast,Channel,Goroutine,我使用服务器将消息从客户端广播/回显到所有连接的客户端。服务器只广播它接收到的第一条消息,尽管它仍然接收消息——fmt.Println([]字节(buf))仍然从客户端打印新消息——并且新客户端可以连接(但它们的消息也不会被广播) 在一些反馈之后,看起来有一个goroutine被卡住了。但到目前为止我还没找到哪一个。非常感谢你的帮助 服务器: package main import ( "crypto/tls" "encoding/binary" "fmt" "

我使用服务器将消息从客户端广播/回显到所有连接的客户端。服务器只广播它接收到的第一条消息,尽管它仍然接收消息——fmt.Println([]字节(buf))仍然从客户端打印新消息——并且新客户端可以连接(但它们的消息也不会被广播)

在一些反馈之后,看起来有一个goroutine被卡住了。但到目前为止我还没找到哪一个。非常感谢你的帮助

服务器:

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)
    }
}
一次广播后(广播无效): 这是一次广播后的状态。服务器将不再广播任何消息

 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

只是对代码的一些注释。您必须测试这是否解决了问题:

在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
这有两种效果:

  • 由于goroutines不必等待另一方做好准备,因此事情将运行得更快/更顺利
  • 如果有一个复杂的goroutine循环,每个goroutine都在另一端等待,这可能会解决您的卡住问题
对所有其他频道也这样做,尽管我假设
进入
离开
不需要它

编辑:

写入连接时缺少一些错误检查。也许那里出了点问题:

func clientWriter(conn net.Conn, ch <-chan string) {
    for msg := range ch {
        fmt.Fprintln(conn, msg) // add error checking here
    }
}

func clientWriter(conn net.conn,ch不认为这能解决您的问题,但是
defer conn.Close()
永远不会在无限循环中执行,您应该在handleConn函数中调用该延迟。当单个连接在写入时阻塞时,广播程序将阻塞。要进行调试,我建议通过发送一个SIGQUIT来转储goroutine堆栈。感谢您的想法。明天将尝试它。您认为
cli堆栈跟踪将我可能会把你引向这个问题。在给代码添加调试代码之前先转储堆栈。好的,请查看我的更新帖子。谢谢你的评论!很有意义,我相应地更改了代码。不幸的是,它无法解决上述问题。我在回答中添加了另一种可能性。谢谢!添加了错误检查,这看起来运行顺利ly或至少不会产生错误。接下来,我将按照ThunderCat的建议转储堆栈。如果您实现,您可以在执行堆栈时通过浏览器检查堆栈,以查看每个goroutine当前正在做/或没有做什么。谢谢,我使用了http/pprof,请查看我的更新问题。braodcaster goroutine似乎是22号d在工作吗?
func clientWriter(conn net.Conn, ch <-chan string) {
    for msg := range ch {
        fmt.Fprintln(conn, msg) // add error checking here
    }
}