问题描述
我有一个 go 应用程序,它使用 github.com/jlaffaye/ftp 下载文件,这是一个实现文件传输协议 (FTP) 的库
定义一个带有 FTP 连接的结构
type Client struct {
conn *ftp.ServerConn
sync.Mutex
}
var cli *Client = nil
然后我将其初始化并分配给以后要使用的全局变量
conn,err := ftp.Dial(cfg.Host+cfg.Port,ftp.DialWithContext(ctx))
if err != nil {
return fmt.Errorf("ftp dial error: %v",err)
}
err = conn.Login(cfg.Username,pwd)
if err != nil {
return fmt.Errorf("ftp login error: %v",err)
}
c := &Client{}
c.Lock()
c.conn = conn
cli = c
c.Unlock()
我有一个 http 处理程序,它从 Client 结构中获取 conn 字段并调用
fileNames,err := conn.NameList(".")
if err != nil {
return err
}
大多数情况下,应用程序在调用 conn.NameList(".")
时失败并出现错误
write tcp xxx.xxx.xx.x:48572-\u003exx.xxx.xxx.xxx:21: write: broken pipe
有时
write tcp xxx.xxx.xx.xx:63037-\u003exx.xxx.xxx.xxx:21: wsasend: An established connection was aborted by the software in your host machine
我不会过早关闭连接。 有没有人知道为什么会这样?或者您可以推荐一个更好的使用 FTP 的库?
根据多个服务是否同时运行的问题,以及它是否同时安全。
当一个进程正在运行时,另一个进程在 setIsRunning(false) is called
之前无法运行
func (s *Service) setIsRunning(b bool) error {
mu := &sync.Mutex{}
mu.Lock()
defer mu.Unlock()
if b && s.isRunning {
return errors.New("already running")
}
s.isRunning = b
return nil
}
尝试在运行时调用该处理程序将产生
"error":"already running"
我也在像这样从全局 Client
读取时使用互斥锁
cli.Lock()
conn = cli.conn
cli.Unlock()
解决方法
切换到非全局客户端可以解决问题