Go语言简单实现FTP协议.

fyxichen · · 4099 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

package ftp

import (
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
	"strings"
)

type Ftp struct {
	con net.Conn
	ip  string
}

func NewFtp(ip string) (*Ftp, error) {
	buf := make([]byte, 1024)
	con, err := net.Dial("tcp", ip)
	if err != nil {
		return nil, err
	}
	n, err := con.Read(buf)
	if err != nil {
		return nil, err
	}
	fmt.Println(string(buf[:n]))
	return &Ftp{con, ip}, nil
}
func (self *Ftp) Login(user, pass string) error {
	buf := make([]byte, 1024)
	self.con.Write([]byte(fmt.Sprintf("USER %s\r\n", user)))
	self.con.Read(buf)
	self.con.Write([]byte(fmt.Sprintf("PASS %s\r\n", pass)))
	n, err := self.con.Read(buf)
	if err != nil {
		return err
	}
	if !strings.Contains(string(buf[:n]), "230 Logged on") {
		return errors.New(strings.TrimSpace(string(buf)))
	}
	return nil
}

func (self *Ftp) PutPasv(Pathname string) error {
	con, err := self.connection("STOR", Pathname)
	if err != nil {
		return err
	}
	File, err := os.Open(Pathname)
	if err != nil {
		con.Close()
		return err
	}
	io.Copy(con, File)
	File.Close()
	con.Close()
	buf := make([]byte, 1024)
	_, err = self.con.Read(buf)
	if err != nil {
		return err
	}
	return nil
}
func (self *Ftp) GetFile(Pathname string) error {
	con, err := self.connection("RETR", Pathname)
	if err != nil {
		return err
	}
	File, err := os.Create(Pathname)
	if err != nil {
		con.Close()
		return err
	}
	io.Copy(File, con)
	File.Close()
	con.Close()
	buf := make([]byte, 1024)
	_, err = self.con.Read(buf)
	if err != nil {
		return err
	}
	return nil
}
func (self *Ftp) connection(status, Pathname string) (net.Conn, error) {
	buf := make([]byte, 1024)
	self.con.Write([]byte("PASV \r\n"))
	n, err := self.con.Read(buf)
	if err != nil {
		return nil, err
	}
	if s := string(buf[:n]); !strings.Contains(s, "227 Entering Passive Mode") {
		return nil, errors.New(s)
	}
	port := getport(buf[27 : n-3])
	con, err := net.Dial("tcp", fmt.Sprintf("%s:%d", strings.Split(self.ip, ":")[0], port))
	if err != nil {
		return nil, err
	}
	self.con.Write([]byte(fmt.Sprintf("%s %s\r\n", status, Pathname)))
	n, err = self.con.Read(buf)
	if err != nil {
		con.Close()
		return nil, err
	}
	if !strings.Contains(string(buf[:n]), "150 Opening data channel") {
		con.Close()
		return nil, errors.New("create data link error.")
	}
	return con, nil
}
func getport(by []byte) int {
	s := string(by)
	list := strings.Split(s, ",")
	n1, err := strconv.Atoi(list[len(list)-2])
	if err != nil {
		return 0
	}
	n2, err := strconv.Atoi(list[len(list)-1])
	if err != nil {
		return 0
	}
	return n1*256 + n2
}

版权声明:本文为博主原创文章,未经博主允许不得转载。


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:fyxichen

查看原文:Go语言简单实现FTP协议.

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4099 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传