ホームページ  >  記事  >  バックエンド開発  >  golangはftp機能を実装します

golangはftp機能を実装します

王林
王林オリジナル
2023-05-15 09:58:372266ブラウズ

FTP (ファイル転送プロトコル) は、サーバーとクライアントの間でファイルをアップロードおよびダウンロードするために使用できる一般的なファイル転送プロトコルです。 Go 言語は、高い効率と同時実行パフォーマンスを備えたオープンソース プログラミング言語です。この記事ではGo言語を使ってFTP機能を実装する方法を紹介します。

  1. FTP プロトコルの概要

FTP プロトコルはクライアント/サーバー モデルに基づいており、クライアントはサーバーにリクエストを送信してファイルをアップロードまたはダウンロードします。 FTP クライアント プログラムは、TCP プロトコルを使用して FTP サーバーと通信し、FTP サーバーはポート 21 で待機します。FTP クライアントは、FTP サーバーとのデータ通信に異なるポート番号を使用します。 FTP プロトコルは、ファイル共有、Web サイトのファイル管理、バックアップなどのシナリオで一般的に使用されます。

  1. FTP サーバーの実装

FTP サーバーはポート 21 をリッスンし、クライアントから送信された FTP コマンドを解析する必要があります。通常、FTP クライアントは認証のためにユーザー名とパスワードを FTP サーバーに送信します。認証が成功すると、FTP クライアントはファイルのダウンロード、アップロード、ファイルの削除などのさまざまな FTP コマンドを実行できるようになります。

次に、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
"))
        }
    }
}

この例では、標準ライブラリの net パッケージを使用して TCP サーバーを実装します。サーバーはポート番号をリッスンし、新しい接続を受信したときに処理するために handleConnection 関数を呼び出します。 handleConnection 関数は、まず「220 Welcome to FTP Server」メッセージをクライアントに送信します。次に、サーバーはクライアントがユーザー名とパスワードを送信するのを待ち、bufio パッケージの ReadString 関数を呼び出してクライアントから送信されたメッセージを読み取ります。受信したメッセージが「USER」で始まる場合は、ユーザー名を保存し、「331 Password required」メッセージをクライアントに送信し、クライアントがパスワードを入力するのを待ちます。受信したメッセージが「PASS」で始まる場合は、パスワードが正しいことを確認してください。検証が成功すると、ユーザーが正常にログインしたことを示す「230 Logged on」メッセージがクライアントに送信されます。パスワードの検証が失敗した場合、「530 認証に失敗しました」というメッセージがクライアントに送信されます。受信したメッセージが「QUIT」で始まる場合、「221 Goodbye」メッセージがクライアントに送信され、クライアントとの接続が切断されます。

  1. FTP クライアントの実装

FTP クライアントは、FTP サーバーと通信するためのコードを実装する必要があります。 FTP クライアントは通常、コマンド ラインまたは GUI インターフェイスを通じてユーザーと対話し、アップロード、ダウンロード、削除、名前変更などの機能を提供します。

以下は簡単な 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+"
")
    }
}

この例では、FTP クライアントは標準ライブラリの net パッケージを使用して実装されています。クライアントはコマンド ライン インターフェイスを通じてユーザーと対話します。まず、クライアントはダイヤル機能を介して FTP サーバーに接続します。その後、クライアントは FTP サーバーからメッセージを継続的に受信し、コマンド ライン インターフェイスに出力します。次に、クライアントはユーザーがコマンドを入力するのを待ち、Fprintf 関数を通じてコマンドを FTP サーバーに送信します。その後、クライアントは FTP サーバーからの応答を待ち続けます。

  1. FTP ファイルのアップロードとダウンロードの実装

FTP クライアントは、STOR コマンドを使用してファイルをアップロードし、RETR コマンドを使用してファイルをダウンロードできます。 STOR コマンドは FTP サーバーにファイルをアップロードし、RETR コマンドは FTP サーバーからファイルをダウンロードします。

次は、単純な 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]))
}

この例では、FTP クライアントは、ファイルをアップロードおよびダウンロードするために「STOR」および「RETR」コマンドを実装します。 handleFileUpload 関数は、ユーザーが入力したファイル名からファイルを開き、ファイル サイズを FTP サーバーに送信します。次に、この関数はファイルの内容をチャンクで読み取り、FTP サーバーに送信します。 handleFileDownload 関数は、FTP サーバーからデータを受信し、新しく作成されたファイルにそれを書き込みます。 handleServerResponse 関数は、FTP サーバーから応答を読み取り、コンソールに出力します。

    #結論
FTP サーバーとクライアントは Go 言語を使用して簡単に実装できます。 FTP サーバーと FTP クライアント間の通信は、標準ライブラリの net パッケージと bufio パッケージを通じて実現されます。さらに、Go 言語は効率的な同時プログラミングもサポートしており、FTP ファイルのアップロードおよびダウンロード機能をより適切に実装できます。

以上がgolangはftp機能を実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。