Go语言基于TCP实现简易聊天工具的示例代码

顾言
顾言
发布时间:2026-10-15| 3人浏览过
原创

本文演示如何使用 Go 语言标准库中的 net 包构建一个基于 TCP 协议的简易命令行聊天工具。主要包含服务端(Server)与客户端(Client)两部分代码,涉及 TCP 监听、接受连接、goroutine 并发处理以及基础的网络 I/O 操作,旨在帮助开发者理解 Go 在网络编程中的基本工作流。

核心原理与结构准备

该聊天工具采用 C/S(客户端/服务器)架构。服务端负责监听指定端口并等待客户端接入,每当有新连接建立时,便启动一个新的协程(goroutine)来单独处理该连接的读写交互。客户端则负责向服务端发起连接,并在终端中循环输入与显示消息。

第1步:服务端代码实现 (server.go)

目的: 启动 TCP 监听服务,接收客户端连接并处理双向通信。
关键组件:
- net.Listen: 创建 TCP 监听器。
- listen.Accept: 阻塞等待直到有客户端连接。
- go process(conn): 使用协程并发处理每个连接,避免阻塞主循环。
- bufio.NewReader(os.Stdin): 用于读取用户在终端输入的回复消息。

package main
 
import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
)
 
// process 函数负责处理单个客户端连接的读写交互
type process struct{}
func (p *process) Run(conn net.Conn) {
	defer conn.Close() // 确保连接在函数退出时关闭
	
	var tmp [128]byte
	reader := bufio.NewReader(os.Stdin) // 创建标准输入读取器
	
	for {
		// 1. 从网络连接读取客户端发来的数据
		n, err := conn.Read(tmp[:])
		if err != nil {
			fmt.Printf("read from connection failed, err:%v\n", err)
			break
		}
		// 打印收到的客户端消息
		fmt.Println("Client:", string(tmp[:n]))
		
		// 2. 提示用户输入服务端回复
		fmt.Print("Server:")
		text, _ := reader.ReadString('\n')
		msg := strings.TrimSpace(text) // 去除首尾空格及换行符
		
		// 3. 将用户输入的消息写回连接
		_, err = conn.Write([]byte(msg))
		if err != nil {
			fmt.Printf("write to connection failed, err:%v\n", err)
			break
		}
	}
}

func main() {
	// 监听 TCP 端口,此处设置为本地 10086
	listen, err := net.Listen("tcp", "127.0.0.1:10086")
	if err != nil {
		fmt.Printf("start server failed, err:%v\n", err)
		return
	}
	defer listen.Close() // 建议关闭监听器
	
	fmt.Println("Server listening on 127.0.0.1:10086...")
	
	// 4. 循环接受新连接
	for {
		conn, err := listen.Accept()
		if err != nil {
			fmt.Printf("accept failed, err:%v\n", err)
			continue
		}
		// 5. 为每个新连接启动一个 goroutine 进行处理
		go func(c net.Conn) {
			p := &process{}
			p.Run(c)
		}(conn)
	}
}

第2步:客户端代码实现 (client.go)

目的: 连接到服务端,并在循环中实现用户输入发送与服务端响应接收。
关键逻辑:
- net.Dial: 建立与服务端的 TCP 连接。
- 循环检测输入,若输入 exit 则断开连接。
- 同时处理用户输入和网络读取,保持交互流畅。

package main
 
import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
)
 
func main() {
	// 1. 建立与服务端的 TCP 连接
	conn, err := net.Dial("tcp", "127.0.0.1:10086")
	if err != nil {
		fmt.Printf("connection failed, err:%v", err)
		return
	}
	defer conn.Close() // 确保退出前关闭连接
	
	var msg string
	var tmp [128]byte
	reader := bufio.NewReader(os.Stdin) // 标准输入读取器
	
	for {
		// 2. 提示用户输入消息
		fmt.Print("Client:")
		text, _ := reader.ReadString('\n')
		msg = strings.TrimSpace(text)
		
		// 退出条件判断
		if msg == "exit" {
			break
		}
		
		// 3. 将消息写入网络连接发送给服务端
		_, err := conn.Write([]byte(msg))
		if err != nil {
			fmt.Printf("write failed, err:%v", err)
			return
		}
		
		// 4. 从网络连接读取服务端返回的数据
		n, err := conn.Read(tmp[:])
		if err != nil {
			fmt.Printf("read from server failed, err:%v", err)
			return
		}
		// 打印服务端回复
		fmt.Println("Server:", string(tmp[:n]))
	}
}

运行效果与测试

在实际运行中,建议先启动服务端程序,再打开另一个终端启动客户端程序。以下是典型的交互流程模拟:

D:\Software\godata\src\demo\server> go run server.go
Server listening on 127.0.0.1:10086...
Client: 你好
Server: hello
Client: 很高兴见到你
Server: 我也是
Client: exit

注意事项与排错

  • 端口冲突: 如果运行时报错 bind: address already in use,说明 10086 端口已被占用,请修改代码中的端口号或关闭占用该端口的进程。
  • 连接中断: 如果客户端非正常退出(如强制关闭窗口),服务端可能无法立即感知连接断开,导致后续 Read 阻塞。在生产环境中通常需要心跳机制或超时设置来处理僵尸连接。
  • 缓冲区大小: 示例中使用了 [128]byte 作为缓冲区,适用于简短文本。若传输大文件,需调整缓冲区大小或使用分块传输。

以上就是 Go 语言实现基于 TCP 的简易聊天小工具的详细内容,更多关于 Go 语言网络编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。