doubu1950 2018-09-22 15:26
浏览 49
已采纳

创建服务器并连接到它

I'm trying to create a server and connect to it in Go but when the server starts running, no functions after it are called because the function that starts the server appears to be blocking. I tried using a goroutine to run the server in the background so that other code can be executed but that's not really working either. I'm getting an error that I don't understand

panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x496757]

Here is my code for the server

func RunServer(port string) {

    fmt.Println("Launching server...")
    ln, err := net.Listen("tcp", port)
    conn, _ := ln.Accept()

    // run loop forever (or until ctrl-c)
    for {

        // will listen for message to process ending in newline (
)
        message, _ := bufio.NewReader(conn).ReadString('
')

        // output message received
        fmt.Print("Message Received:", string(message))

        // sample process for string received
        newmessage := strings.ToUpper(message)

        // send new string back to client
        conn.Write([]byte(newmessage + "
"))
    }
}

And here is the code for the client.

func createInitalClient(port int) {

    // run server then create a client that connects to it
    portToRunOn := fmt.Sprintf("%s%d", ":", port)
    go RunServer(portToRunOn)
}

func main() {

    createInitalClient(5000)

    // connect to this socket
    conn, _ := net.Dial("tcp", "127.0.0.1:5000")

    for {
        // read in input from stdin

        reader := bufio.NewReader(os.Stdin)
        fmt.Print("Text to send: ")
        text, _ := reader.ReadString('
')

        // send to socket
        fmt.Fprintf(conn, text+"
")

        // listen for reply
        message, _ := bufio.NewReader(conn).ReadString('
')
        fmt.Print("Message from server: " + message)
    }
}

Am I doing this right or is there another approach to do what I'm trying to do? I'm a little hesistant to use goroutines because introducing async behavior might be wrong in my case.

EDIT 1: looks like this error is happening because the client is trying to connect to the server before it starts.

EDIT 2: I (might have) fixed this by adding a boolean channel in the server that returns true right before the listeners starts accepting connections. Then the client only connects to the server if the value coming from the channel is true. I'm not sure if this is the correct fix in this scenario but it appears to be working.

  • 写回答

1条回答 默认 最新

  • douze1332 2018-09-22 18:10
    关注

    Your server is started in a goroutine, which is spawned asynchronously by the Go runtime and will take some time to be scheduled and executed. Specifically, the runtime will not wait for the server goroutine to be started before continuing execution of the main function.

    You either need to:

    • arrange for the server goroutine to communicate when the server is ready to accept connections – use of a channel is an acceptable mechanism for this; or
    • have your client connection attempt to connect repeatedly until the connection is accepted – in effect polling the server's readiness state. For example:

      // Predeclare "conn" to ensure it remains in scope outside the loop
      var conn net.Conn
      
      for {
          var err error
          conn, err = net.Dial("tcp", "127.0.0.1:5000")
      
          // Failed connection, try again in a second.
          // TODO: limit the number of attempts before giving up.
          if err != nil {
              time.Sleep(time.Second)
              continue
          }
      
          // Connected successfully. Continue.
          break
      }
      
      // do something with "conn"
      

    Error values

    As noted in a comment to your question, your code ignores error values in several places.

    Please don't do this in real production code. Errors are returned for a reason, and may indicate a problem external to your code which prevents your program from properly continuing execution. You need to check for error values and take appropriate action where they are returned. The other value(s) returned from a function call, especially anything in the standard library, are unlikely to be meaningful if the returned error is not nil.

    Yes, you end up writing if err != nil a lot. That's expected, and there are various patterns you can employ in some cases to avoid making your code seem excessively repetitive.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染