并发性| goroutines | golang |缓冲读卡器

时间:2017-04-21 02:51:56

标签: go concurrency udp bufferedreader

相信我或者误解了常规如何运作,读者如何工作或两者兼而有之。

期待 goroutine的异步执行(缓冲读取器,for循环读取缓冲区,等待来自服务器的消息)

在客户端拨打服务器之前,尝试 METHOD A呼叫go xyz();所以xyz()创建缓冲区并开始在后台阅读。然后,客户端拨打服务器;服务器发回消息;客户端正在读取缓冲区,因此,它获取消息并打印到控制台

实际上发生了什么客户端将消息发送到服务器,但在读取服务器可能的回复时却没有在缓冲区中拾取任何内容;所以它是并发运行的,因为我知道for循环没有停止,但它让下一行代码执行(客户端向服务器发送消息)。

但是当 METHOD B我没有同时调用xyz()时,在客户端拨打服务器后,所有内容都按预期工作。客户端从服务器获取消息并打印到控制台。

方法A ,我们有订单:

///////////// 步骤1和2位于由go xyz()

调用的goroutine中
  1. 创建缓冲阅读器
  2. for循环 - 从服务器读取缓冲区 - 打印输出
  3. 客户端拨打服务器

    go xyz(conn, p)

    fmt.Fprintf(conn, "Give me a hash to work on ...")

  4. 方法B ,我们有订单:

    ///////////// 第2步和第3步是在xyz()

    调用的goroutine中
    1. 客户端拨打服务器
    2. 创建缓冲阅读器
    3. for循环 - 从服务器读取缓冲区的信息 - 打印出来

      fmt.Fprintf(conn, "Give me a hash to work on ...")

      xyz(conn, p)

    4. client.go

      package main
      import (
          "fmt"
          "net"
          "bufio"
      )
      
      func xyz(conn net.Conn, p []byte) {
        rd := bufio.NewReader(conn)
        for {
          _, err := rd.Read(p)
          if err == nil {
            fmt.Printf("SERVER : %s\n", p)
          } else {
              fmt.Printf("Some error %v\n", err)
          }
        }
      }
      
      func main() {
          p :=  make([]byte, 2048)
          conn, err := net.Dial("udp", "127.0.0.1:1234")
          if err != nil {
              fmt.Printf("Some error %v", err)
              return
          }
      
          go xyz(conn, p)
          fmt.Fprintf(conn, "Give me a hash to work on ...")
      }
      

      server.go

      package main
      import (
          "fmt"
          "net"
      )
      
      
      func sendResponse(conn *net.UDPConn, addr *net.UDPAddr, hash string) {
          _,err := conn.WriteToUDP([]byte("Hello, here is the hash  - " + hash), addr)
          if err != nil {
              fmt.Printf("Couldn't send response %v", err)
          }
      }
      
      
      func main() {
          hash := "36";
          p := make([]byte, 2048)
          addr := net.UDPAddr{
              Port: 1234,
              IP: net.ParseIP("127.0.0.1"),
          }
          ser, err := net.ListenUDP("udp", &addr)
          if err != nil {
              fmt.Printf("Some error %v\n", err)
              return
          }
          for {
              _, remoteaddr, err := ser.ReadFromUDP(p)
              fmt.Printf("CLIENT : %v : %s\n", remoteaddr, p)
              if err !=  nil {
                  fmt.Printf("Some error  %v", err)
                  continue
              }
              go sendResponse(ser, remoteaddr, hash)
          }
      }
      

1 个答案:

答案 0 :(得分:2)

  

The Go Programming Language Specification

     

Go statements

     

“go”语句开始执行函数调用   独立的并发控制线程,或goroutine,在   相同的地址空间。

     

...与常规调用不同,程序执行不会等待   要完成的调用函数。

client.go启动goroutine xyz,然后继续执行终止程序的main函数的末尾。该程序不会等待xyz goroutine运行或完成。