目錄
2. Handling Client Connections
3. Adding Graceful Shutdown (Optional but Recommended)
4. Testing Your Server
首頁 後端開發 Golang 從頭開始編寫TCP服務器

從頭開始編寫TCP服務器

Jul 31, 2025 am 10:17 AM
go語言 tcp伺服器

使用net.Listen 創建TCP 監聽器,監聽指定端口。 2. 通過listener.Accept 接受連接,並用goroutine 並發處理。 3. 在handleConnection 中讀取客戶端數據並回顯。 4. 使用context 和signal 實現優雅關閉,等待連接完成。 5. 通過telnet 或nc 測試服務器。 Go 的net 包提供了完整的TCP 編程能力,結合goroutine 可輕鬆實現高並發,通過defer 確保連接關閉,使用context 和WaitGroup 實現優雅關閉,該服務器雖簡單但可擴展,支持自定義協議或添加TLS,是一個功能完整且易於理解的基礎TCP 服務器實現。

Writing a TCP Server in Go from Scratch

Writing a TCP server in Go doesn't require much code, thanks to Go's excellent standard library and lightweight concurrency model. While you wouldn't typically write a production server “from scratch” without leveraging existing packages, building a basic one yourself helps you understand how network programming works in Go. Here's how to create a simple TCP server step by step, using only the standard net package.

Writing a TCP Server in Go from Scratch

1. Setting Up a Basic TCP Listener

The foundation of any TCP server is a listener that waits for incoming connections on a specific port. In Go, this is done using the net.Listen function.

 package main

import (
    "log"
    "net"
)

func main() {
    // Listen on TCP port 8080
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal("Failed to bind to port 8080:", err)
    }
    defer listener.Close()

    log.Println("Server listening on :8080")

    for {
        // Accept incoming connections
        conn, err := listener.Accept()
        if err != nil {
            log.Println("Failed to accept connection:", err)
            continue
        }

        // Handle each connection in a new goroutine
        go handleConnection(conn)
    }
}

This sets up a server that listens on port 8080 and enters a loop to accept incoming connections. Each connection is then passed to a handler function in a separate goroutine — this is where Go shines, making concurrent handling simple and efficient.

Writing a TCP Server in Go from Scratch

2. Handling Client Connections

Once a client connects, you can read data from and write data to the connection using standard I/O operations.

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

    buffer := make([]byte, 1024)

    for {
        // Read data from the client
        n, err := conn.Read(buffer)
        if err != nil {
            log.Println("Connection closed by client:", err)
            return
        }

        // Echo back the received data
        message := buffer[:n]
        log.Printf("Received: %s", message)

        _, err = conn.Write([]byte("Echo: " string(message)))
        if err != nil {
            log.Println("Failed to send response:", err)
            return
        }
    }
}

This handler reads up to 1024 bytes at a time, logs the message, and sends an "Echo" response back to the client. The loop continues until the client closes the connection or an error occurs.

Writing a TCP Server in Go from Scratch

? Note: This is a basic echo server. Real protocols (like HTTP, Redis, or custom binary formats) would involve parsing the incoming bytes according to a specific format.


For production-like behavior, you might want to stop the server gracefully when receiving a signal (like Ctrl C).

 package main

import (
    "context"
    "log"
    "net"
    "os"
    "os/signal"
    "sync"
    "syscall"
)

func main() {
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal("Failed to bind to port 8080:", err)
    }
    defer listener.Close()

    log.Println("Server listening on :8080")

    // Wait group to track active connections
    var wg sync.WaitGroup

    // Channel to signal shutdown
    ctx, stop := context.WithCancel(context.Background())
    defer stop()

    // Goroutine to listen for interrupt signals
    go func() {
        sigCh := make(chan os.Signal, 1)
        signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
        <-sigCh
        log.Println("\nShutting down server...")
        stop()
        listener.Close() // This will unblock Accept()
    }()

    // Accept loop
    for {
        conn, err := listener.Accept()
        select {
        case <-ctx.Done():
            break
        default:
        }

        if err != nil {
            // Check if context was canceled
            select {
            case <-ctx.Done():
                log.Println("Server stopped accepting new connections.")
                break
            default:
                log.Println("Failed to accept connection:", err)
                continue
            }
        }

        wg.Add(1)
        go func(c net.Conn) {
            defer wg.Done()
            handleConnection(c)
        }(conn)
    }

    // Wait for all connections to finish
    wg.Wait()
    log.Println("All connections closed. Server stopped.")
}

Now the server can be stopped gracefully with Ctrl C , and it waits for active connections to finish before exiting.


4. Testing Your Server

You can test the server using telnet or nc (netcat):

 telnet localhost 8080

Then type a message:

 Trying 127.0.0.1...
Connected to localhost.
Escape character is &#39;^]&#39;.
Hello
Echo: Hello

Or use nc :

 echo "Hi" | nc localhost 8080
# Output: Echo: Hi

Key Points to Remember

  • Go's net package provides all you need for low-level TCP programming.
  • Each connection should be handled in a separate goroutine to support concurrency.
  • Always close connections ( defer conn.Close() ) to avoid resource leaks.
  • Use context and sync.WaitGroup for graceful shutdowns.
  • Buffer sizes (like 1024 bytes) are arbitrary — real applications may need dynamic reading (eg, using bufio.Scanner or length-prefixed messages).

Basically, that's a fully functional TCP server in Go. It's minimal, educational, and extensible — you can build custom protocols, add TLS, or implement message framing on top. Not complex, but powerful.

以上是從頭開始編寫TCP服務器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

PHP教程
1596
276
在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? 在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? Apr 02, 2025 pm 04:54 PM

Go語言中使用RedisStream實現消息隊列時類型轉換問題在使用Go語言與Redis...

GoLand中自定義結構體標籤不顯示怎麼辦? GoLand中自定義結構體標籤不顯示怎麼辦? Apr 02, 2025 pm 05:09 PM

GoLand中自定義結構體標籤不顯示怎麼辦?在使用GoLand進行Go語言開發時,很多開發者會遇到自定義結構體標籤在�...

在Go編程中,如何正確管理Mysql和Redis的連接與釋放資源? 在Go編程中,如何正確管理Mysql和Redis的連接與釋放資源? Apr 02, 2025 pm 05:03 PM

Go編程中的資源管理:Mysql和Redis的連接與釋放在學習Go編程過程中,如何正確管理資源,特別是與數據庫和緩存�...

centos postgresql資源監控 centos postgresql資源監控 Apr 14, 2025 pm 05:57 PM

CentOS系統下PostgreSQL數據庫資源監控方案詳解本文介紹多種監控CentOS系統上PostgreSQL數據庫資源的方法,助您及時發現並解決潛在性能問題。一、利用PostgreSQL內置工具和視圖PostgreSQL自帶豐富的工具和視圖,可直接用於性能和狀態監控:pg_stat_activity:查看當前活動連接和查詢信息。 pg_stat_statements:收集SQL語句統計信息,分析查詢性能瓶頸。 pg_stat_database:提供數據庫層面的統計數據,例如事務數、緩存命中

去其他語言:比較分析 去其他語言:比較分析 Apr 28, 2025 am 12:17 AM

goisastrongchoiceforprojectsneedingsimplicity,績效和引發性,butitmaylackinadvancedfeatures and ecosystemmaturity.1)

GO中初始功能的常見用例 GO中初始功能的常見用例 Apr 28, 2025 am 12:13 AM

thecommonusecasesfortheinitfunctionoare:1)加載configurationfilesbeforeThemainProgramStarts,2)初始化的globalvariables和3)runningpre-checkSorvalidationsbeforEtheprofforeTheProgrecce.TheInitFunctionIsautefunctionIsautomentycalomationalmatomatimationalycalmatemationalcalledbebeforethemainfuniinfuninfuntuntion

在同一個包內的不同文件中如何使用小寫名稱的函數? 在同一個包內的不同文件中如何使用小寫名稱的函數? Apr 02, 2025 pm 05:00 PM

如何在同一個包內的不同文件中使用小寫名稱的函數?在Go...

後端開發語言性能PK:哪種語言最省資源? 後端開發語言性能PK:哪種語言最省資源? Apr 02, 2025 pm 04:27 PM

後端開發語言性能比較:資源利用率的探討選擇合適的編程語言和框架對於後端開發至關重要,尤其是在資源利...

See all articles