如何在net.Con&中正确地分组消息睡眠预防广播

时间:2014-05-05 11:50:25

标签: go

更新了解决方案: http://play.golang.org/p/Skgk9reT6c

http://play.golang.org/p/gtWYPXRsKo

没有goroutines: http://play.golang.org/p/Vgne7e3RVO

问题1:为什么消息"你永远不会看到我!"没有显示?

问题2:一旦我发起客户端,我就会发送这些消息,所有这些消息都在他们自己的线程上:

func client() {
  net, _ := net.Dial("tcp", "127.0.0.1:9988")
  go clientBroadcast(net,"123456789101112")
  go clientBroadcast(net,"do dododo do dodo do")
  go clientBroadcast(net,"123456789101112")
  go clientBroadcast(net,"do dododo do dodo do")
  go clientBroadcast(net,"123456789101112")
  go clientBroadcast(net,"TWELVE!")
  time.Sleep(100 * time.Millisecond)
  go clientBroadcast(net,"YOU'LL NEVER SEE ME!")
}

服务器接收它们并打印出来:

func serverBroadcast(con net.Conn, ch chan string) {
  buf := make([]byte, 1024)
  bytenum, _ := con.Read(buf)
  strin := string(buf[0:bytenum])
  fmt.Printf("\n Server Broadcasting Message {%v}\n",string(strin))
}

服务器显然是一次接收所有4条消息而不是一次接收一条消息?

我收到此消息:

  

服务器广播消息{123456789101112do dododo do dodo   do123456789101112do dododo do dodo do123456789101112TWELVE!}

     

服务器广播消息{123456789101112do dododo do dodo   do123456789101112do dododo do dodo do123456789101112TWELVE!}

     

服务器广播消息{123456789101112do dododo do dodo   do123456789101112do dododo do dodo do123456789101112TWELVE!}

但是我会假设我应该收到这个(按照随机顺序,因为它们都是线程化的)

  

服务器广播消息{123456789101112}

     

服务器广播消息{do dododo do dodo}

     

服务器广播消息{123456789101112}

     

服务器广播消息{do dododo do dodo}

     

服务器广播消息{TWELVE!}

     

服务器广播消息{123456789101112}

     

服务器广播消息{do dododo do dodo}

     

服务器广播消息{123456789101112}

     

服务器广播消息{do dododo do dodo}

     

服务器广播消息{TWELVE!}

     

服务器广播消息{123456789101112}

     

服务器广播消息{do dododo do dodo}

     

服务器广播消息{123456789101112}

     

服务器广播消息{do dododo do dodo}

     

服务器广播消息{TWELVE!}

1 个答案:

答案 0 :(得分:3)

问题在于,在此功能中,您无法读取流上的所有可用数据。您需要多次致电Read才能获取所有数据。

func serverBroadcast(con net.Conn, ch chan string) {
    buf := make([]byte, 1024)
    bytenum, _ := con.Read(buf)
    strin := string(buf[0:bytenum])
    fmt.Printf("\n Server Broadcasting Message {%v}\n", string(strin))
}

但是,如果你这样做,你会发现它会阻止,(playground),例如

func serverBroadcast(con net.Conn, ch chan string) {
    buf := make([]byte, 1024)
    for {
        bytenum, err := con.Read(buf)
        if err != nil {
            fmt.Printf("Err %v", err)
            return
        }
        strin := string(buf[0:bytenum])
        fmt.Printf("\n Server Broadcasting Message {%v}\n", string(strin))
    }
}

您需要通过TCP分隔您的消息,或者在消息之前发送计数,以便知道消息的开始和结束位置(如果您想避免阻止)