1. 网络编程的"交通规则"

网络编程就像城市交通系统,数据包就是行驶的车辆。Go语言自带的net包就像交通管理局,帮我们管理着这些"数据车辆"的通行规则。咱们先来认识几个核心概念:

  • TCP:像快递公司的保价服务,确保每个包裹都准确送达
  • UDP:像普通明信片投递,寄出就不管了
  • Socket:相当于每家每户的邮箱,既是发送口也是接收口
// 基础TCP服务器示例(技术栈:Go标准库net包)
package main

import (
    "net"
    "log"
)

func main() {
    // 申请一个"邮箱"(监听端口)
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal("邮箱申请失败:", err)
    }
    defer listener.Close() // 记得关邮箱

    for {
        // 等待邮差送来信件
        conn, err := listener.Accept()
        if err != nil {
            log.Println("收信出错:", err)
            continue
        }
        
        // 专门派个快递员处理这封信
        go handleRequest(conn)
    }
}

func handleRequest(conn net.Conn) {
    defer conn.Close() // 处理完记得关门
    buffer := make([]byte, 1024)
    
    // 读取信件内容
    n, err := conn.Read(buffer)
    if err != nil {
        log.Println("读信出错:", err)
        return
    }
    
    // 原样寄回回执
    conn.Write(buffer[:n])
}

2. TCP/UDP双雄争霸

2.1 TCP的可靠传输

应用场景:文件传输、网页访问、数据库连接等需要可靠性的场景

示例升级版:带超时的TCP客户端

package main

import (
    "net"
    "time"
    "fmt"
)

func main() {
    // 带超时设置的拨号
    conn, err := net.DialTimeout("tcp", "localhost:8080", 3*time.Second)
    if err != nil {
        fmt.Println("连接超时:", err)
        return
    }
    defer conn.Close()

    // 设置读写超时
    conn.SetDeadline(time.Now().Add(5 * time.Second))

    // 发送消息
    message := "你好,TCP服务器!"
    _, err = conn.Write([]byte(message))
    if err != nil {
        fmt.Println("发送失败:", err)
        return
    }

    // 接收回显
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        fmt.Println("接收失败:", err)
        return
    }

    fmt.Printf("收到回信: %s\n", string(buffer[:n]))
}

2.2 UDP的轻量快车

应用场景:实时视频、DNS查询、在线游戏等时效性优先的场景

UDP服务端示例

package main

import (
    "net"
    "log"
)

func main() {
    // 创建UDP地址
    addr, err := net.ResolveUDPAddr("udp", ":9090")
    if err != nil {
        log.Fatal("地址解析失败:", err)
    }

    // 绑定UDP端口
    conn, err := net.ListenUDP("udp", addr)
    if err != nil {
        log.Fatal("监听失败:", err)
    }
    defer conn.Close()

    buffer := make([]byte, 1024)
    for {
        // 直接读取客户端数据(不需要Accept)
        n, clientAddr, err := conn.ReadFromUDP(buffer)
        if err != nil {
            log.Println("读取失败:", err)
            continue
        }

        // 原样返回给客户端
        _, err = conn.WriteToUDP(buffer[:n], clientAddr)
        if err != nil {
            log.Println("发送失败:", err)
        }
    }
}

3. HTTP服务的魔法世界

Go的net/http包像瑞士军刀,帮我们快速搭建Web服务

RESTful API示例

package main

import (
    "encoding/json"
    "net/http"
    "sync"
)

var (
    users   = make(map[string]string)
    mutex   sync.RWMutex
)

type User struct {
    Username string `json:"username"`
    Email    string `json:"email"`
}

func main() {
    http.HandleFunc("/users", handleUsers)
    http.ListenAndServe(":8080", nil)
}

func handleUsers(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case "GET":
        mutex.RLock()
        defer mutex.RUnlock()
        json.NewEncoder(w).Encode(users)
        
    case "POST":
        var user User
        if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }
        
        mutex.Lock()
        users[user.Username] = user.Email
        mutex.Unlock()
        
        w.WriteHeader(http.StatusCreated)
        
    default:
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
}

4. WebSocket实时通信

使用gorilla/websocket实现实时聊天(技术栈:gorilla/websocket)

package main

import (
    "log"
    "net/http"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

func main() {
    http.HandleFunc("/chat", chatHandler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func chatHandler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("升级WebSocket失败:", err)
        return
    }
    defer conn.Close()

    for {
        // 读取客户端消息
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println("读取错误:", err)
            return
        }

        // 原样返回消息
        if err := conn.WriteMessage(messageType, p); err != nil {
            log.Println("写入错误:", err)
            return
        }
    }
}

5. 技术选型指南

应用场景对照表

协议 适用场景 典型应用
TCP 可靠数据传输 SSH、HTTP、数据库连接
UDP 实时性要求高 视频会议、在线游戏
HTTP Web服务交互 REST API、网页访问
WebSocket 双向实时通信 在线聊天、实时监控

Go网络编程优势

  1. 高并发:goroutine轻量级线程
  2. 简洁API:标准库设计优雅
  3. 高性能:基于epoll/kqueue的事件驱动
  4. 跨平台:一套代码多平台运行

注意事项

  1. 资源泄漏:务必defer Close()
  2. 并发控制:使用sync包处理共享资源
  3. 超时设置:避免僵尸连接
  4. 错误处理:网络操作必须检查错误
  5. 缓冲区管理:预防内存泄漏

6. 关联技术扩展

6.1 Context超时控制

在网络请求处理中合理使用context:

func handleRequest(ctx context.Context, conn net.Conn) {
    // 创建带超时的上下文
    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
    defer cancel()

    done := make(chan struct{})
    
    go func() {
        // 业务处理逻辑
        time.Sleep(10*time.Second) // 模拟耗时操作
        done <- struct{}{}
    }()

    select {
    case <-done:
        conn.Write([]byte("处理完成"))
    case <-ctx.Done():
        conn.Write([]byte("请求超时"))
    }
}

7. 实战总结

通过本文的旅程,我们完成了:

  1. 基础TCP/UDP服务搭建
  2. HTTP RESTful API开发
  3. WebSocket实时通信实现
  4. 并发控制与错误处理实践

学习建议

  • 从标准库net包入手,理解基本范式
  • 使用go test -race检测并发问题
  • 结合pprof进行性能分析
  • 关注连接池管理等高级话题

Go的网络编程就像搭积木,标准库提供了丰富的构建模块。记住:安全驾驶(正确处理并发)、定期保养(资源管理)、遵守交规(协议规范),就能在网络的数字世界中畅通无阻!