Golang实现UDP和TCP服务器的方法与比较

Golang实现UDP和TCP服务器的方法与比较 如何让服务器同时响应UDP和TCP请求?我们的任务是构建一个QOTD服务器,目前已经实现了TCP响应,但不知道如何实现UDP响应。

// 此处放置Go代码示例
3 回复

net 包为 TCP 和 UDP 提供了相关工具。

但你的问题描述不够清晰。你想构建哪种类型的服务器?它应该具备怎样的行为特征?你目前已经完成了哪些部分?

更多关于Golang实现UDP和TCP服务器的方法与比较的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你不需要创建一个服务器,而是需要创建两个:一个用于TCP,一个用于UDP,它们分别在不同的goroutine中运行,但在同一个主包中。查看示例这里

以下是使用Go语言实现同时响应UDP和TCP请求的QOTD(Quote of the Day)服务器的方法。我将提供一个完整的示例,展示如何在一个程序中处理两种协议。

实现方案

通过goroutine并发运行TCP和UDP服务器,共享相同的业务逻辑(生成QOTD响应)。

package main

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

// QOTD响应内容
const quote = "The only way to do great work is to love what you do. - Steve Jobs"

// 处理TCP连接
func handleTCPConnection(conn net.Conn) {
    defer conn.Close()
    conn.Write([]byte(quote + "\n"))
}

// 处理UDP请求
func handleUDPRequest(conn *net.UDPConn) {
    buffer := make([]byte, 1024)
    
    for {
        n, addr, err := conn.ReadFromUDP(buffer)
        if err != nil {
            fmt.Printf("UDP read error: %v\n", err)
            continue
        }
        
        fmt.Printf("Received UDP request from %s: %s", addr.String(), string(buffer[:n]))
        
        // 发送QOTD响应
        _, err = conn.WriteToUDP([]byte(quote+"\n"), addr)
        if err != nil {
            fmt.Printf("UDP write error: %v\n", err)
        }
    }
}

func main() {
    tcpAddr := ":17" // QOTD标准端口
    udpAddr := ":17"
    
    // 启动TCP服务器
    tcpListener, err := net.Listen("tcp", tcpAddr)
    if err != nil {
        fmt.Printf("TCP listen error: %v\n", err)
        return
    }
    defer tcpListener.Close()
    
    fmt.Printf("TCP QOTD server listening on %s\n", tcpAddr)
    
    // 启动UDP服务器
    udpAddrParsed, err := net.ResolveUDPAddr("udp", udpAddr)
    if err != nil {
        fmt.Printf("UDP resolve error: %v\n", err)
        return
    }
    
    udpConn, err := net.ListenUDP("udp", udpAddrParsed)
    if err != nil {
        fmt.Printf("UDP listen error: %v\n", err)
        return
    }
    defer udpConn.Close()
    
    fmt.Printf("UDP QOTD server listening on %s\n", udpAddr)
    
    // 并发处理TCP连接
    go func() {
        for {
            conn, err := tcpListener.Accept()
            if err != nil {
                fmt.Printf("TCP accept error: %v\n", err)
                continue
            }
            fmt.Printf("Accepted TCP connection from %s\n", conn.RemoteAddr().String())
            go handleTCPConnection(conn)
        }
    }()
    
    // 处理UDP请求(在主goroutine中)
    handleUDPRequest(udpConn)
}

协议比较

TCP特性:

  • 面向连接,保证数据顺序和可靠性
  • 适合需要可靠传输的场景
  • 在QOTD中:建立连接→发送引用→关闭连接

UDP特性:

  • 无连接,不保证可靠性和顺序
  • 开销小,响应快
  • 在QOTD中:单次请求-响应模式,无需建立连接

测试方法

使用netcat工具测试服务器:

# 测试TCP
echo "" | nc localhost 17

# 测试UDP
echo "" | nc -u localhost 17

关键区别

  1. 连接管理:TCP需要Accept()连接,UDP直接处理数据包
  2. 错误处理:TCP连接错误会终止会话,UDP可继续处理其他请求
  3. 并发模型:TCP为每个连接启动goroutine,UDP使用单goroutine处理所有请求

这个实现满足了QOTD协议的要求,同时保持了代码的简洁性和高效性。

回到顶部