Maison  >  Article  >  développement back-end  >  golang implémente la fonction ftp

golang implémente la fonction ftp

王林
王林original
2023-05-15 09:58:372197parcourir

FTP (File Transfer Protocol) est un protocole de transfert de fichiers courant qui peut être utilisé pour télécharger et télécharger des fichiers entre serveurs et clients. Le langage Go est un langage de programmation open source offrant une efficacité et des performances de concurrence élevées. Cet article explique comment utiliser le langage Go pour implémenter la fonction FTP.

  1. Présentation du protocole FTP

Le protocole FTP est basé sur le modèle client-serveur, dans lequel le client envoie une demande au serveur pour télécharger ou télécharger des fichiers. Le programme client FTP utilise le protocole TCP pour communiquer avec le serveur FTP et le serveur FTP écoute sur le port 21. Le client FTP utilise différents numéros de port pour la communication de données avec le serveur FTP. Le protocole FTP est couramment utilisé dans des scénarios tels que le partage de fichiers, la gestion de fichiers de sites Web et la sauvegarde.

  1. Implémentation du serveur FTP

Le serveur FTP doit écouter le port 21 et analyser les commandes FTP envoyées par le client. En règle générale, un client FTP envoie un nom d'utilisateur et un mot de passe au serveur FTP pour authentification. Une fois l'authentification réussie, le client FTP peut exécuter diverses commandes FTP, telles que télécharger des fichiers, télécharger des fichiers, supprimer des fichiers, etc.

Ce qui suit est un exemple de code pour implémenter un serveur FTP :

package main

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

func main() {
    arguments := os.Args
    if len(arguments) == 1 {
        fmt.Println("Please provide a port number")
        return
    }

    PORT := ":" + arguments[1]
    l, err := net.Listen("tcp4", PORT)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer l.Close()

    fmt.Println("Listening on " + PORT)

    for {
        conn, err := l.Accept()
        if err != nil {
            fmt.Println(err)
            continue
        }
        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    fmt.Println("Received connection from " + conn.RemoteAddr().String())
    conn.Write([]byte("220 Welcome to FTP Server
"))
    username := ""
    for {
        message, err := bufio.NewReader(conn).ReadString('
')
        if err != nil && err.Error() == "EOF" {
            break
        }
        fmt.Print("Message Received:", string(message))
        command := strings.TrimSpace(string(message))
        parts := strings.Split(command, " ")
        if parts[0] == "USER" {
            username = parts[1]
            conn.Write([]byte("331 Password required for " + username + "
"))
        } else if parts[0] == "PASS" {
            password := parts[1]
            if username == "admin" && password == "password" {
                conn.Write([]byte("230 Logged on
"))
            } else {
                conn.Write([]byte("530 Authentication failed
"))
            }
        } else if parts[0] == "QUIT" {
            conn.Write([]byte("221 Goodbye
"))
            conn.Close()
            break
        } else {
            conn.Write([]byte("500 Command not implemented
"))
        }
    }
}

Dans cet exemple, un serveur TCP est implémenté à l'aide du package net de la bibliothèque standard. Le serveur écoute le numéro de port et appelle la fonction handleConnection pour traiter la réception d'une nouvelle connexion. La fonction handleConnection envoie d'abord un message « 220 Welcome to FTP Server » au client. Ensuite, le serveur attend que le client envoie le nom d'utilisateur et le mot de passe, et lit le message envoyé par le client en appelant la fonction ReadString dans le package bufio. Si le message reçu commence par « USER », enregistrez le nom d'utilisateur et envoyez un message « 331 Mot de passe requis » au client, en attendant que le client saisisse un mot de passe. Si le message reçu commence par « PASS », vérifiez que le mot de passe est correct. Si la vérification réussit, un message « 230 Connecté » est envoyé au client, indiquant que l'utilisateur s'est connecté avec succès. Si la vérification du mot de passe échoue, un message « 530 Échec de l'authentification » est envoyé au client. Si le message reçu commence par « QUIT », un message « 221 Goodbye » est envoyé au client et la connexion avec le client est fermée.

  1. Implémentation du client FTP

Le client FTP doit implémenter le code pour communiquer avec le serveur FTP. Les clients FTP interagissent généralement avec les utilisateurs via la ligne de commande ou l'interface graphique, fournissant des fonctions telles que le téléchargement, la suppression et le renommage.

Ce qui suit est un exemple simple de client FTP :

package main

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

func main() {
    arguments := os.Args
    if len(arguments) == 1 {
        fmt.Println("Please provide a host:port string")
        return
    }

    CONNECT := arguments[1]
    c, err := net.Dial("tcp4", CONNECT)
    if err != nil {
        fmt.Println(err)
        return
    }

    for {
        message, err := bufio.NewReader(c).ReadString('
')
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Print("Message Received:", string(message))
        if strings.Contains(strings.ToLower(message), "goodbye") {
            return
        }

        fmt.Print(">> ")
        commandReader := bufio.NewReader(os.Stdin)
        command, _ := commandReader.ReadString('
')
        fmt.Fprintf(c, command+"
")
    }
}

Dans cet exemple, le client FTP est implémenté à l'aide du package net dans la bibliothèque standard. Le client interagit avec l'utilisateur via l'interface de ligne de commande. Tout d'abord, le client se connecte au serveur FTP via la fonction Dial. Le client reçoit ensuite en permanence des messages du serveur FTP et les imprime sur l'interface de ligne de commande. Ensuite, le client attend que l'utilisateur entre une commande et envoie la commande au serveur FTP via la fonction Fprintf. Le client continue ensuite d'attendre une réponse du serveur FTP.

  1. Implémenter le téléchargement et le téléchargement de fichiers FTP

Le client FTP peut utiliser la commande STOR pour télécharger des fichiers et la commande RETR pour télécharger des fichiers. La commande STOR télécharge des fichiers sur un serveur FTP, tandis que la commande RETR télécharge des fichiers depuis un serveur FTP.

Ce qui suit est un exemple simple de téléchargement et de téléchargement de fichiers FTP :

package main

import (
    "fmt"
    "io"
    "net"
    "os"
)

func main() {
    arguments := os.Args
    if len(arguments) == 1 {
        fmt.Println("Please provide a host:port string")
        return
    }

    CONNECT := arguments[1]
    c, err := net.Dial("tcp4", CONNECT)
    if err != nil {
        fmt.Println(err)
        return
    }

    for {
        var input string
        fmt.Scanln(&input)

        if input == "STOP" {
            fmt.Println("Exiting FTP Client")
            return
        }

        if input == "RETR" {
            fmt.Fprintf(c, input+"
")
            handleFileDownload(c)
        } else if input == "STOR" {
            fmt.Fprintf(c, input+"
")
            handleFileUpload(c)
        } else {
            fmt.Fprintf(c, input+"
")
            handleServerResponse(c)
        }
    }
}

func handleFileDownload(conn net.Conn) {
    var filename string
    fmt.Scanln(&filename)

    file, err := os.Create(filename)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer file.Close()

    data := make([]byte, 2048)
    for {
        n, err := conn.Read(data)
        if err != nil && err != io.EOF {
            fmt.Println(err)
            return
        }
        if n == 0 {
            fmt.Println("Download complete")
            return
        }

        _, err = file.Write(data[:n])
        if err != nil {
            fmt.Println(err)
            return
        }
    }
}

func handleFileUpload(conn net.Conn) {
    var filename string
    fmt.Scanln(&filename)

    file, err := os.Open(filename)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer file.Close()

    fileInfo, err := file.Stat()
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Fprintf(conn, "%d
", fileInfo.Size())
    data := make([]byte, 2048)
    for {
        n, err := file.Read(data)
        if err != nil && err != io.EOF {
            fmt.Println(err)
            return
        }
        if n == 0 {
            fmt.Println("Upload complete")
            return
        }

        _, err = conn.Write(data[:n])
        if err != nil {
            fmt.Println(err)
            return
        }
    }
}

func handleServerResponse(conn net.Conn) {
    response := make([]byte, 2048)
    n, err := conn.Read(response)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(response[:n]))
}

Dans cet exemple, le client FTP implémente les commandes "STOR" et "RETR" pour télécharger et télécharger des fichiers. La fonction handleFileUpload ouvre le fichier à partir du nom de fichier saisi par l'utilisateur et envoie la taille du fichier au serveur FTP. La fonction lit ensuite le contenu du fichier par morceaux et l'envoie au serveur FTP. La fonction handleFileDownload reçoit les données du serveur FTP et les écrit dans le fichier nouvellement créé. La fonction handleServerResponse lit la réponse du serveur FTP et l'imprime sur la console.

  1. Conclusion

Le serveur et le client FTP peuvent être facilement implémentés à l'aide du langage Go. La communication entre le serveur FTP et le client FTP est implémentée via le package net et le package bufio dans la bibliothèque standard. De plus, le langage Go prend également en charge une programmation simultanée efficace, qui peut mieux implémenter les fonctions de téléchargement et de téléchargement de fichiers FTP.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn