golang socket(三) TCP协议 实现聊天功能 TCPConn

UDP

func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)

go 复制代码
// 1. 构造监听地址 
addr := &net.UDPAddr{ Port: 8080, // 监听 8080 端口 IP: nil, // nil = 监听所有网卡 } 
// 2. 创建 UDP 监听(调用源码函数) 
conn, err := net.ListenUDP("udp", addr)

读取数据 func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error)

go 复制代码
buf := make([]byte, 1024) // 创建接收缓冲区 

// 调用 UDP 读方法(阻塞直到收到包) 
n, clientAddr, err := conn.ReadFromUDP(buf) 
// n 收到多少字节 
// clientAddr 客户端的 IP+port(必须存下来才能回消息) 
// buf[:n] 收到的数据

发数据 func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error)

go 复制代码
// 给刚才发送消息的客户端回消息 
msg := []byte("hello from udp server") 
// 发送消息(必须带客户端地址) 
conn.WriteToUDP(msg, clientAddr)

客户端连接 func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error)

go 复制代码
// 要连接的服务端地址 
serverAddr := &net.UDPAddr{ IP: net.ParseIP("127.0.0.1"), Port: 8080, } 
// 连接 UDP 服务端 
conn, err := net.DialUDP("udp", nil, serverAddr)
go 复制代码
package main

import (
        "encoding/binary"
        "net"
        "strconv"
        "time"
)

const headerSize = 5 // 1B类型 + 4B长度

func main() {
        // UDP 监听
        conn, err := net.ListenUDP("udp", &net.UDPAddr{Port: 8080})
        if err != nil {
                panic(err)
        }
        defer conn.Close()

        println("UDP 服务器启动 :8080")

        buf := make([]byte, 1024)
        for {
                // UDP 读数据
                n, addr, _ := conn.ReadFromUDP(buf)

                // 开协程处理(和TCP模型一样)
                go handleUDPClient(conn, addr, buf[:n])
        }
}

// UDP 处理逻辑(极简)
func handleUDPClient(conn *net.UDPConn, addr *net.UDPAddr, data []byte) {
        // 解包头
        if len(data) < headerSize {
                return
        }

        pkgType := data[0]
        bodyLen := binary.BigEndian.Uint32(data[1:5])
        totalLen := headerSize + int(bodyLen)

        if len(data) != totalLen {
                return
        }

        body := data[headerSize:]
        println("UDP 收到:type=", pkgType, " data=", string(body))

        // 回复消息(带时间戳)
        t := time.Now().Unix()
        timeStr := strconv.FormatInt(t, 10)
        replyBody := []byte("UDP Hello " + timeStr)

        // 组包
        pkg := make([]byte, headerSize+len(replyBody))
        pkg[0] = 1
        binary.BigEndian.PutUint32(pkg[1:5], uint32(len(replyBody)))
        copy(pkg[headerSize:], replyBody)

        // UDP 回复
        conn.WriteToUDP(pkg, addr)
}
go 复制代码
package main

import (
        "encoding/binary"
        "net"
)

const headerSize = 5

func main() {
        conn, _ := net.Dial("udp", "127.0.0.1:8080")
        defer conn.Close()

        body := []byte("UDP Client Hello")
        pkg := make([]byte, headerSize+len(body))
        pkg[0] = 1
        binary.BigEndian.PutUint32(pkg[1:5], uint32(len(body)))
        copy(pkg[headerSize:], body)

        conn.Write(pkg)
}
相关推荐
XovH13 小时前
Docker 网络入门:桥接、自定义与主机网络
后端
Kir1to13 小时前
线程的三种创建方式与生命周期及线程池
后端
Rust研习社13 小时前
MSRV 是什么?一文说清楚
后端·rust·编程语言
XovH13 小时前
Docker 网络进阶:容器间通信与 DNS 解析
后端
月読h13 小时前
Hermes QQbot websocket Problems
后端
Byron__13 小时前
SpringBoot 核心面试知识点(自动配置/启动流程/注解/Starter)
spring boot·后端·面试
程序员cxuan13 小时前
这个插件,直接让 Java 小白秒变资深开发
人工智能·后端·程序员
ZengLiangYi13 小时前
Prompt 工程:让 LLM 输出结构化 JSON
前端·javascript·后端
Oo_行者_oO13 小时前
MyBatis-Plus 字段数学计算封装
后端