Home  >  Article  >  Backend Development  >  golang implements ftp function

golang implements ftp function

王林
王林Original
2023-05-15 09:58:372197browse

FTP (File Transfer Protocol) is a common file transfer protocol that can be used to upload and download files between the server and the client. Go language is an open source programming language with high efficiency and concurrency performance. This article will introduce how to use Go language to implement FTP function.

  1. FTP Protocol Overview

The FTP protocol is based on the client-server model, where the client sends a request to the server to upload or download files. The FTP client program uses the TCP protocol to communicate with the FTP server, and the FTP server listens on port 21. The FTP client uses different port numbers for data communication with the FTP server. The FTP protocol is commonly used in scenarios such as file sharing, website file management, and backup.

  1. Implementing the FTP server

The FTP server needs to listen to port 21 and parse the FTP commands sent by the client. Typically, an FTP client sends a username and password to the FTP server for authentication. Once the authentication is successful, the FTP client can execute various FTP commands, such as downloading files, uploading files, deleting files, etc.

The following is a sample code to implement an FTP server:

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
"))
        }
    }
}

In this example, a TCP server is implemented using the net package of the standard library. The server listens on the port number and calls the handleConnection function to process when a new connection is received. The handleConnection function first sends a "220 Welcome to FTP Server" message to the client. Next, the server waits for the client to send the username and password, and reads the message sent by the client by calling the ReadString function in the bufio package. If the received message begins with "USER", save the username and send a "331 Password required" message to the client, waiting for the client to enter a password. If the received message begins with "PASS", verify that the password is correct. If the verification is successful, a "230 Logged on" message is sent to the client, indicating that the user has successfully logged in. If password verification fails, a "530 Authentication failed" message is sent to the client. If the received message begins with "QUIT", a "221 Goodbye" message is sent to the client and the connection to the client is closed.

  1. Implementing the FTP client

The FTP client needs to implement the code to communicate with the FTP server. FTP clients usually interact with users through the command line or GUI interface, providing functions such as uploading, downloading, deleting, and renaming.

The following is a simple FTP client example:

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+"
")
    }
}

In this example, the FTP client is implemented using the net package in the standard library. The client interacts with the user through the command line interface. First, the client connects to the FTP server through the Dial function. The client then continuously receives messages from the FTP server and prints them to the command line interface. Next, the client waits for the user to enter a command and sends the command to the FTP server through the Fprintf function. The client then continues to wait for a response from the FTP server.

  1. Implementing FTP file upload and download

The FTP client can use the STOR command to upload files and the RETR command to download files. The STOR command uploads files to an FTP server, while the RETR command downloads files from an FTP server.

The following is a simple FTP file upload and download example:

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]))
}

In this example, the FTP client implements the "STOR" and "RETR" commands to upload and download files. The handleFileUpload function opens the file from the file name entered by the user and sends the file size to the FTP server. The function then reads the file contents in chunks and sends them to the FTP server. The handleFileDownload function receives data from the FTP server and writes it to the newly created file. The handleServerResponse function reads the response from the FTP server and prints it to the console.

  1. Conclusion

FTP server and client can be easily implemented using Go language. Communication between the FTP server and FTP client is realized through the net package and bufio package in the standard library. In addition, the Go language also supports efficient concurrent programming, which can better implement FTP file upload and download functions.

The above is the detailed content of golang implements ftp function. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn