用Go写一个能扛住大量连接的TCP服务
现在很多后台服务都跑在云端,比如聊天系统、实时监控、物联网设备通信。这些场景下,服务器得同时处理成百上千个设备的连接。如果用传统方式写,一个连接卡住,整个服务就卡住了。这时候就得上并发模型。
Go 语言天生适合干这事,goroutine 轻量又高效,写并发 TCP 服务特别顺手。下面直接上一个实际可用的例子,既能处理多个客户端同时连接,又能避免常见安全隐患。
基础并发TCP服务器结构
这个例子启动一个TCP服务,每个新连接都会启一个独立的goroutine去处理。这样不会因为某个客户端读写慢而拖累其他连接。
package main
import (
"bufio"
"fmt"
"net"
"time"
)
func handleConnection(conn net.Conn) {
defer conn.Close()
// 设置超时,防止恶意客户端长时间占用连接
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
msg := scanner.Text()
fmt.Printf("收到消息: %s\n", msg)
// 简单回显
response := fmt.Sprintf("已收到: %s\n", msg)
conn.Write([]byte(response))
// 处理完一次就退出,避免无限占用
break
}
}
func main() {
listener, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
defer listener.Close()
fmt.Println("TCP 服务已启动,监听 :8080")
for {
conn, err := listener.Accept()
if err != nil {
fmt.Printf("接受连接失败: %v\n", err)
continue
}
// 每个连接开一个协程处理
go handleConnection(conn)
}
}为什么这样写更安全
很多人写TCP服务时只顾着通,忽略了防。比如不设读取超时,攻击者可以建立连接后一直不发数据,慢慢耗光服务器资源。上面代码里用了 SetReadDeadline,10秒内没动静就自动断开。
另外,每个连接处理完立刻退出,不维持长会话,减少被利用的风险。如果你真需要长连接,建议加上心跳机制和最大存活时间。
加点防护让服务更稳
真实环境中,你可能还要限制单位时间内单IP的连接数。可以用 map + 定时清理的方式做简单限流,或者集成 redis 做分布式计数。
还有,日志别只往屏幕打。生产环境要把每条连接的IP、时间、交互内容记下来,出了问题能快速定位。比如有人不停连上来发乱码,一看日志就知道是扫描行为。
Go 的标准库虽然简单,但配上合理的逻辑,完全可以写出既快又稳的 TCP 服务。关键不是代码多复杂,而是有没有把安全当成默认配置来写。