分享
Go语言简单实现FTP协议.
fyxichen · · 4596 次点击 · · 开始浏览这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
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
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信4596 次点击
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
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
}
版权声明:本文为博主原创文章,未经博主允许不得转载。