17 Fortgeschrittene Netzwerkprogrammierung

Go bietet starke Unterstützung für die Netzwerkprogrammierung durch die Pakete net und net/http. Diese Pakete ermöglichen es uns, Netzwerkanwendungen einfach zu erstellen, sei es auf niedriger oder hoher Abstraktionsebene.

17.0.1 Erstellen eines einfachen TCP-Servers

Beginnen wir mit der Erstellung eines einfachen TCP-Servers:

package main

import (
    "bufio"
    "fmt"
    "net"
    "strings"
)

func handleConnection(conn net.Conn) {
    defer conn.Close()
    for {
        message, _ := bufio.NewReader(conn).ReadString('\n')
        fmt.Print("Message received: ", string(message))
        newMessage := strings.ToUpper(message)
        conn.Write([]byte(newMessage + "\n"))
    }
}

func main() {
    fmt.Println("Server started...")
    ln, _ := net.Listen("tcp", ":8080")
    defer ln.Close()
    for {
        conn, _ := ln.Accept()
        go handleConnection(conn)
    }
}

In diesem Beispiel:

  1. Wir erstellen einen TCP-Listener, der auf Port 8080 wartet.
  2. Wir akzeptieren eingehende Verbindungen und starten eine Goroutine, um jede Verbindung zu handhaben.
  3. Die Funktion handleConnection liest Nachrichten vom Client, konvertiert sie in Großbuchstaben und sendet sie zurück.

17.0.2 Erstellen eines einfachen HTTP-Servers

Nun erstellen wir einen einfachen HTTP-Server:

package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, Go HTTP Server!")
}

func main() {
    http.HandleFunc("/hello", helloHandler)
    fmt.Println("Server started at :8080")
    http.ListenAndServe(":8080", nil)
}

In diesem Beispiel:

  1. Wir definieren einen Handler helloHandler, der eine einfache Begrüßung an den Client sendet.
  2. Wir registrieren den Handler für den Pfad /hello.
  3. Wir starten den HTTP-Server, der auf Port 8080 lauscht.

17.1 Erstellen eines HTTP-Clients

Neben dem Server müssen wir manchmal auch HTTP-Clients erstellen, um Anfragen an andere Dienste zu senden. Hier ein einfaches Beispiel:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    resp, err := http.Get("http://example.com")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Println("Response Body:", string(body))
}

In diesem Beispiel:

  1. Wir senden eine HTTP-GET-Anfrage an http://example.com.
  2. Wir lesen die Antwort und drucken den Inhalt des Antwortkörpers aus.

17.2 WebSockets

WebSockets ermöglichen eine bidirektionale Kommunikation zwischen Client und Server. Hier ein einfaches Beispiel für die Implementierung eines WebSocket-Servers mit dem Paket gorilla/websocket:

17.2.1 Installation des Pakets

Installieren Sie das Paket:

go get github.com/gorilla/websocket

17.2.2 WebSocket-Server

package main

import (
    "fmt"
    "net/http"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

func handleConnections(w http.ResponseWriter, r *http.Request) {
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer ws.Close()

    for {
        messageType, message, err := ws.ReadMessage()
        if err != nil {
            fmt.Println(err)
            break
        }
        fmt.Println("Received: ", string(message))
        if err := ws.WriteMessage(messageType, message); err != nil {
            fmt.Println(err)
            break
        }
    }
}

func main() {
    http.HandleFunc("/ws", handleConnections)
    fmt.Println("WebSocket server started at :8080")
    http.ListenAndServe(":8080", nil)
}

In diesem Beispiel:

  1. Wir definieren einen WebSocket-Upgrader, der HTTP-Verbindungen in WebSocket-Verbindungen umwandelt.
  2. Die Funktion handleConnections behandelt eingehende WebSocket-Verbindungen, liest Nachrichten und sendet sie zurück (Echo-Server).
  3. Wir registrieren den Handler für den Pfad /ws und starten den HTTP-Server.