5.5 سرور udp پیشرفته

5.5 سرور udp پیشرفته

در قسمت قبل به ایجاد یک سرور udp ساده و ارسال پکت به آن پرداختیم. در این قسمت با استفاده از یک سرور و کلاینت udp یک پیام رسان بصورت feed میسازیم. عملکرد سرور و کلاینت: یک سرور udp ایجاد میکنیم که تمام کانکشن های موجود را ذخیره میکند و به محض دریافت پیام از هر یک از کانکشن ها پیام را برای تمام کانکشن های دیگر بجر کانکشن ارسال کننده پیام ارسال میکند.

در مرحله اول سروری که کانکشن ها و ارسال پیام را مدیریت میکنید مینویسیم:

package main

import (
    "fmt"
    "net"
)

func main() {
    // Set up the server
    addr := net.UDPAddr{
        Port: 8000,
        IP:   net.ParseIP("0.0.0.0"),
    }

    conn, err := net.ListenUDP("udp", &addr)
    if err != nil {
        fmt.Println("Error listening:", err)
        return
    }

    defer conn.Close()
    fmt.Println("Server started on port", addr.Port)

    // Listen for incoming messages
    buffer := make([]byte, 1024)

    clients := make(map[string]*net.UDPAddr)

    for {
        n, clientAddr, err := conn.ReadFromUDP(buffer)
        if err != nil {
            fmt.Println("Error reading:", err)
            continue
        }

        // Add new client
        if _, ok := clients[clientAddr.String()]; !ok {
            clients[clientAddr.String()] = clientAddr
            fmt.Println("New client joined:", clientAddr.String())
        }

        // Broadcast message to all clients
        message := buffer[:n]
        for _, addr := range clients {
            if addr.String() != clientAddr.String() {
                _, err = conn.WriteToUDP(message, addr)
                if err != nil {
                    fmt.Println("Error broadcasting message:", err)
                }
            }
        }
    }
}

در این قسمت یک سرور udp ایجاد کرده ایم و هر کانکشن جدید را به لیست کانکشن های خود اضافه میکنیم. همچنین در ازای هر پیام دریافتی از سمت کانکشن ها آن را برای کانکشن های دیگر ارسال میکنیم.

در ادامه یک کلاینت ساده برای سرور خود مینویسیم که پیام هارا نمایش دهد و متن ورودی در ترمینال را به سرور ارسال کند.

package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
)

func main() {
    // Set up connection to the server
    conn, err := net.Dial("udp", "localhost:8000")
    if err != nil {
        fmt.Println("Error connecting:", err)
        return
    }
    defer conn.Close()


    go func() {
        for {
            buf := make([]byte, 1024) // buffer for incoming message
            n, err := conn.Read(buf)
            if err != nil {
                fmt.Println("Error receiving message:", err)
                continue
            }
            fmt.Printf("Received message: %s\n", string(buf[:n]))
        }
    }()

    // Read input from terminal and send to server
    scanner := bufio.NewScanner(os.Stdin)
    for {
		    // send messages to server
        fmt.Print("Enter message: ")
        if !scanner.Scan() {
            break
        }
        message := scanner.Text()
        _, err = conn.Write([]byte(message))
        if err != nil {
            fmt.Println("Error sending message:", err)
            continue
        }
    }
}

در این کد ما تمام پیام های دریافتی از سرور را چاپ میکنیم و هر پیامی که کاربر در ترمینال وارد کند را به سرور ارسال میکنیم.

بعد از اتمام کار برای تست کد خود سه ترمینال مجزا بار میکنیم. و در یکی از سرور ها فایل server.go و در دو ترمینال دیگر فایل client.go را اجرا میکنیم.

هر پیامی که توسط هر کلاینتی ارسال شود برای دیگر کلاینت ها قابل مشاهده است.

توجه کنید اسم فایل ها بر اساس اسم انتخابی شما است. همچنین توجه داشته باشید که شما میتوانید هر تعداد دلخواهی کلاینت را اجرا کنید.