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仓库中,其中包含更详细的逐行文档。祝
您一切顺利,编码愉快!
——爱丽丝·威廉姆斯