发布于 2026-01-06 0 阅读
0

Go语言中Socket并发入门 Go语言中Socket并发入门

GoLang 中 Socket 并发入门

GoLang 中 Socket 并发入门

GoLang 中 Socket 并发入门

什么是插座?

套接字(或称“Web套接字”)是一种基于TCP的互联网协议,用于在服务器和一个或多个客户端之间建立实时持久连接。该协议比标准HTTP连接速度更快,允许服务器和客户端之间双向数据传输。它通过HTTP升级请求进行初始化,作为握手操作。之后,服务器和客户端可以随时双向发送数据。套接字通常用于社交动态、聊天客户端、多人游戏、多媒体流和协作开发等应用。

为什么选择 Go 语言?

并发性是我们应用场景(套接字编程)的最大优势,因为它采用了异步设计。此外,Go 语言本身也是一种非常现代的高级语言,能够快速高效地开发成熟的应用程序。而且,我非常喜欢它简洁优雅的风格!:) 不了解 Go 语言?没关系,这是一个很棒的底层项目,可以帮助你了解一些基本概念,特别是 Go 语言的并发特性——goroutine。

项目启动

本教程基于我的开源代码库

创建一个新的项目文件夹,并初始化一个新的 Git 仓库以跟踪更改(即使仅存储在本地)。方法是在新项目文件夹中打开 shell 或命令行窗口,然后运行 ​​`git git repository` git init。在项目文件夹中创建两个子文件夹,分别用于服务器和客户端。在每个子文件夹中运行 `git git repository` 初始化一个 Go 模块。go mod init如果位于 GOPATH 环境变量之外,可能需要提供模块路径。在每个子main.go文件夹中创建两个新文件,分别命名为 `.gitignore` 和 `.gitignore`,作为应用程序的入口点。

套接字服务器

“Hello World”步骤:

package main

import (
    "fmt"
)

const (
    connHost = "localhost"
    connPort = "8080"
    connType = "tcp"
)

func main() {
    fmt.Println("Starting " + connType + " server on " + connHost + ":" + connPort)

}

聆听和主循环:

package main

import (
    "fmt"
    "os"
    "net"
)

const (
    connHost = "localhost"
    connPort = "8080"
    connType = "tcp"
)

func main() {
    fmt.Println("Starting " + connType + " server on " + connHost + ":" + connPort)
    l, err := net.Listen(connType, connHost+":"+connPort)
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        os.Exit(1)
    }
    defer l.Close()

    for {

    }
}

接受客户端连接:

package main

import (
    "fmt"
    "os"
    "net"
)

const (
    connHost = "localhost"
    connPort = "8080"
    connType = "tcp"
)

func main() {
    fmt.Println("Starting " + connType + " server on " + connHost + ":" + connPort)
    l, err := net.Listen(connType, connHost+":"+connPort)
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        os.Exit(1)
    }
    defer l.Close()

    for {
        c, err := l.Accept()
        if err != nil {
            fmt.Println("Error connecting:", err.Error())
            return
        }
        fmt.Println("Client connected.")

        fmt.Println("Client " + c.RemoteAddr().String() + " connected.")
    }
}

同时处理多个客户:

package main

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

const (
    connHost = "localhost"
    connPort = "8080"
    connType = "tcp"
)

func main() {
    fmt.Println("Starting " + connType + " server on " + connHost + ":" + connPort)
    l, err := net.Listen(connType, connHost+":"+connPort)
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        os.Exit(1)
    }
    defer l.Close()

    for {
        c, err := l.Accept()
        if err != nil {
            fmt.Println("Error connecting:", err.Error())
            return
        }
        fmt.Println("Client connected.")

        fmt.Println("Client " + c.RemoteAddr().String() + " connected.")

        go handleConnection(c)
    }
}

func handleConnection(conn net.Conn) {
    buffer, err := bufio.NewReader(conn).ReadBytes('\n')

    if err != nil {
        fmt.Println("Client left.")
        conn.Close()
        return
    }

    log.Println("Client message:", string(buffer[:len(buffer)-1]))

    conn.Write(buffer)

    handleConnection(conn)
}

无客户端测试:

如果你在 Linux 系统上开发,无需先编写客户端应用程序即可测试新的套接字服务器应用程序。go run main.go在 shell 中,从服务器子文件夹运行 `nc` 命令启动套接字服务器。然后运行 ​​`nc` 命令nc localhost 8080,如果需要,请替换主机名和端口号。虽然有一些应用程序可以在 Windows 系统上运行 `nc`(netcat)命令,但我不太清楚哪个是最佳选择。

套接字客户端

“Hello World”步骤:

package main

import (
    "fmt"
)

const (
    connHost = "localhost"
    connPort = "8080"
    connType = "tcp"
)

func main() {
    fmt.Println("Connecting to " + connType + " server " + connHost + ":" + connPort)
}

正在连接服务器:

package main

import (
    "fmt"
)

const (
    connHost = "localhost"
    connPort = "8080"
    connType = "tcp"
)

func main() {
    fmt.Println("Connecting to " + connType + " server " + connHost + ":" + connPort)
}
    conn, err := net.Dial(connType, connHost+":"+connPort)
    if err != nil {
        fmt.Println("Error connecting:", err.Error())
        os.Exit(1)
    }

处理输入并传递响应:

package main

import (
    "fmt"
)

const (
    connHost = "localhost"
    connPort = "8080"
    connType = "tcp"
)

func main() {
    fmt.Println("Connecting to " + connType + " server " + connHost + ":" + connPort)Getting Started with Sockets in GoLang
}
    conn, err := net.Dial(connType, connHost+":"+connPort)
    if err != nil {
        fmt.Println("Error connecting:", err.Error())
        os.Exit(1)
    }
    reader := bufio.NewReader(os.Stdin)

    for {
        fmt.Print("Text to send: ")

        input, _ := reader.ReadString('\n')

        message, _  := bufio.NewReader(conn).ReadString('\n')

        log.Print("Server relay:", message)
    }

测试客户端:

go run main.go在 shell 或命令行中,从服务器项目子文件夹运行 socket 服务器。现在,在客户端文件夹下打开另一个 shell 或命令行会话,并运行go run main.go命令来启动客户端应用程序。客户端中输入的任何文本都会发送到服务器,显示时间戳,然后服务器会将文本转发回来并再次显示。

此测试用于验证套接字服务器-客户端接口的基本功能,可通过扩展 server.go 文件中的 handleConnection 函数来增强其功能。服务器会并发处理每个客户端的连接,连接数量的上限取决于系统运行能力。如果将端口暴露给网络流量,也可以通过其他本地系统或互联网进行连接。

总结

现在,你已经拥有了完全基于标准库 GoLang 编写的独立套接字服务器和客户端接口!那么接下来该做什么呢?可能性无限,你可以编写类似 IRC 的聊天客户端或流媒体应用程序,一步一步来就好。这也是我们创建了一个新的 Git 仓库来管理你之后添加的所有更改的原因之一。

本教程的代码存储在我的开源 GitHub仓库中,其中包含更详细的逐行文档。祝


您一切顺利,编码愉快!
——爱丽丝·威廉姆斯

文章来源:https://dev.to/alicewilliamstech/getting-started-with-sockets-in-golang-2j66