使Golang TCP服务器并发

Fra*_*844 5 concurrency tcp go

Go的新手并试图使TCP服务器并发.我找到了这方面的多个例子,包括这个,但我想弄清楚的是为什么我对非并发版本所做的一些改变不起作用.

这是我开始的原始示例代码

package main
import "bufio"
import "fmt"
import "log"
import "net"
import "strings" // only needed below for sample processing

func main() {
  fmt.Println("Launching server...")
  fmt.Println("Listen on port")
  ln, err := net.Listen("tcp", "127.0.0.1:8081")
  if err != nil {
      log.Fatal(err)
  }
  defer ln.Close()

  fmt.Println("Accept connection on port")
  conn, err := ln.Accept()
  if err != nil {
      log.Fatal(err)
  }

  fmt.Println("Entering loop")
  // run loop forever (or until ctrl-c)
  for {
    // will listen for message to process ending in newline (\n)
    message, _ := bufio.NewReader(conn).ReadString('\n')
    // 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 + "\n"))
  }
}
Run Code Online (Sandbox Code Playgroud)

以上工作,但它不是并发的.

这是我修改后的代码

package main
import "bufio"
import "fmt"
import "log"
import "net"
import "strings" // only needed below for sample processing

func handleConnection(conn net.Conn) {
  fmt.Println("Inside function")
  // run loop forever (or until ctrl-c)
  for {
    fmt.Println("Inside loop")
    // will listen for message to process ending in newline (\n)
    message, _ := bufio.NewReader(conn).ReadString('\n')
    // 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 + "\n"))
  }

}

func main() {
  fmt.Println("Launching server...")
  fmt.Println("Listen on port")
  ln, err := net.Listen("tcp", "127.0.0.1:8081")
  if err != nil {
      log.Fatal(err)
  }
  //defer ln.Close()

  fmt.Println("Accept connection on port")
  conn, err := ln.Accept()
  if err != nil {
      log.Fatal(err)
  }
  fmt.Println("Calling handleConnection")
  go handleConnection(conn)

}
Run Code Online (Sandbox Code Playgroud)

我将我的代码基于我发现的并发服务器的其他几个示例,但是当我运行上面的服务器似乎退出而不是运行handleConnection函数

启动服务器......

听口岸

接受端口连接

调用handleConnection

我会发现任何反馈作为类似的代码示例我发现并使用相同的方法测试,同时调用函数来处理连接,工作; 所以,想知道我看到的其他样本的修改代码有什么不同,因为它们对我来说似乎是一样的.

我不确定这是不是问题,但我试着评论延迟电话关闭.这没有用.

谢谢.

Jim*_*imB 5

您的main函数在接受新连接后立即返回,因此您的程序将在可以处理连接之前退出.由于您可能还希望接收多个单个连接(否则不会出现并发),因此应将其置于for循环中.

您还在for循环的每次迭代中创建一个新的缓冲读取器,这将丢弃任何缓冲的数据.你需要做的是外面的for循环,我这里展示通过创建一个新bufio.Scanner这是一个简单的阅读换行分隔符的文本的方式.

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "strings"
)

func handleConnection(conn net.Conn) {
    defer conn.Close()
    scanner := bufio.NewScanner(conn)
    for scanner.Scan() {
        message := scanner.Text()
        fmt.Println("Message Received:", message)
        newMessage := strings.ToUpper(message)
        conn.Write([]byte(newMessage + "\n"))
    }

    if err := scanner.Err(); err != nil {
        fmt.Println("error:", err)
    }
}

func main() {
    ln, err := net.Listen("tcp", "127.0.0.1:8081")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Accept connection on port")

    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("Calling handleConnection")
        go handleConnection(conn)
    }
}
Run Code Online (Sandbox Code Playgroud)