首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Goroutines:广播在第一条消息后停止工作

Goroutines:广播在第一条消息后停止工作
EN

Stack Overflow用户
提问于 2018-08-29 05:46:44
回答 1查看 303关注 0票数 0

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

经过一些反馈后,似乎有一个goroutine被卡住了。但到目前为止,我还找不到是哪一个。真的很感谢你的帮助。

服务器:

代码语言:javascript
复制
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 160 255 180 73 20 43 129 132 255 207 10 9 130 216 44 38 141 101 17 125 101 4 62 228 221 158 196 41 163 227 253 71 179 172 143 225

Update1:对不起,我不擅长调试。下面是完整的goroutine堆栈转储(工作和不工作)。在我看来,goroutine 8是"runnable",而goroutine 9是"IO wait“和"runtime_pollWait”。有什么办法解决这个问题吗?

服务器启动后的:没有任何来自客户端的事先输入的(连接除外)。在此状态下,广播将工作一次。

代码语言:javascript
复制
   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

一次广播后的(广播不起作用):这是一次广播后的状态。服务器将不再广播任何消息。

代码语言:javascript
复制
 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-在任何消息之前

代码语言:javascript
复制
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-在第一次广播之后-不再广播

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

发布于 2018-08-29 06:08:11

只是对你的代码的一些评论。您将不得不测试这是否解决了问题:

在for循环中有一个延迟永远不会(?)这是个好主意。将延时移动到handleConn函数中:

代码语言:javascript
复制
for {
    conn, err := listener.Accept()
    if err != nil {
        log.Print(err)
        continue
    }
    defer conn.Close() // Not good!
    go handleConn(conn)
}

接下来,我将使用传出通道,并将其设置为缓冲通道:

代码语言:javascript
复制
ch := make(chan string, 10) // outgoing client messages

这有两个效果:

  • 事情将运行得更快/更流畅,因为goroutines不必等待另一端准备就绪
  • 如果存在一个复杂的goroutine循环,每个goroutine都在另一端等待,这可能会解决卡住的问题。

对所有其他通道执行相同的操作,尽管我假设enteringleaving不需要它。

编辑:

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

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

编辑2:

在您的客户端实现net/http/pprof服务器,并检查see服务器的堆端点,它开始查看goroutines挂起的位置。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52066623

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档