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网络编程优势
- 高并发:goroutine轻量级线程
- 简洁API:标准库设计优雅
- 高性能:基于epoll/kqueue的事件驱动
- 跨平台:一套代码多平台运行
注意事项
- 资源泄漏:务必defer Close()
- 并发控制:使用sync包处理共享资源
- 超时设置:避免僵尸连接
- 错误处理:网络操作必须检查错误
- 缓冲区管理:预防内存泄漏
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. 实战总结
通过本文的旅程,我们完成了:
- 基础TCP/UDP服务搭建
- HTTP RESTful API开发
- WebSocket实时通信实现
- 并发控制与错误处理实践
学习建议:
- 从标准库
net
包入手,理解基本范式 - 使用
go test -race
检测并发问题 - 结合
pprof
进行性能分析 - 关注连接池管理等高级话题
Go的网络编程就像搭积木,标准库提供了丰富的构建模块。记住:安全驾驶(正确处理并发)、定期保养(资源管理)、遵守交规(协议规范),就能在网络的数字世界中畅通无阻!