合普知识库
柔彩主题三 · 更轻盈的阅读体验

Go语言TCP编程示例:从零开始写一个简单的聊天程序

发布时间:2026-01-01 02:30:48 阅读:71 次

Go写个TCP服务器其实没那么难

最近在家折腾智能家居,想着能不能自己写个小工具,让手机和树莓派之间传点状态信息。试了HTTP,发现太重,每次都要握手,延迟有点高。后来想到用TCP直接通信,简单又稳定。正好最近在学Go,就顺手用它写了第一个TCP服务端和客户端。

先跑通一个最简单的例子

Go的net包把网络编程封装得很干净。下面这个例子启动一个TCP服务器,监听本地8888端口,只要有人连上来,就发一句“欢迎”:

package main

import (
    "net"
    "log"
)

func main() {
    listener, err := net.Listen("tcp", ":8888")
    if err != nil {
        log.Fatal(err)
    }
    defer listener.Close()

    log.Println("服务器已启动,监听 :8888")

    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Print(err)
            continue
        }

        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    message := "欢迎来到我的小服务器!\n"
    conn.Write([]byte(message))
}

写个客户端试试看

光有服务端不够,还得有个客户端去连。写个简单的,连上去就读服务端发来的消息:

package main

import (
    "net"
    "io/ioutil"
    "log"
)

func main() {
    conn, err := net.Dial("tcp", "localhost:8888")
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    response, err := ioutil.ReadAll(conn)
    if err != nil {
        log.Print(err)
    }

    log.Printf("收到:%s", response)
}

升级成双向聊天模式

上面只能单向发消息,不够意思。改成双方都能说话的模式更实用。比如你家的温控设备可以主动上报温度,手机也能发指令让它调整风速。

关键是在连接处理里开两个goroutine,一个读一个写:

func handleChat(conn net.Conn) {
    defer conn.Close()

    go func() {
        scanner := bufio.NewScanner(conn)
        for scanner.Scan() {
            log.Printf("收到消息:%s", scanner.Text())
        }
    }()

    reader := bufio.NewReader(os.Stdin)
    for {
        fmt.Print("> ")
        text, _ := reader.ReadString('\n')
        conn.Write([]byte(text))
    }
}

当然,真实场景里不会让用户手动输入,而是自动读取传感器数据或解析控制命令。但原理是一样的——通过TCP连接持续交换字节流。

Go的并发模型特别适合这种一对多的连接管理。每个客户端来一条连接,go一下就扔后台跑着,不占主线程。写网络服务的时候,根本不用操心线程池或者回调地狱。

前几天我把这个小程序改了改,部署到家里的服务器上,现在用手机连过去就能看到阳台温湿度,还能远程开关加湿器。虽然功能简单,但全是自己一行行写出来的,用起来格外踏实。