[Go] Golang:gosync 简单文件同步 Simple File Sync →→→→→进入此内容的聊天室

来自 , 2020-11-01, 写在 Go, 查看 151 次.
URL http://www.code666.cn/view/9a3f263a
  1. package main
  2.  
  3. import (
  4.     "os"
  5.     "fmt"
  6.     "net"
  7.     "flag"
  8.     "time"
  9.     "crypto/md5"
  10.     "io"
  11.     "strings"
  12.     "strconv"
  13. )
  14.  
  15. type sysFileInfo struct{
  16.     fName       string
  17.     fSize       int64
  18.     fMtime      time.Time
  19.     fPerm       os.FileMode
  20.     fMd5        string
  21.     fType       bool
  22. }
  23.  
  24. var (
  25.     listenPort = flag.String( "port","7722","server listen port" )
  26.     syncFile = flag.String( "file","","transfer file" )
  27.     syncHost = flag.String( "host","","server host" )
  28.     syncSer = flag.Bool( "d",false,"server mode")
  29.     syncFold = flag.String( "dir","/tmp/gosync/","recive sync fold ")
  30. )
  31.  
  32. func main(){
  33.     flag.Parse()
  34.     if *syncSer {  
  35.         servPort:=fmt.Sprintf( ":%s",*listenPort )
  36.         l,err := net.Listen( "tcp",servPort )
  37.         if err != nil{
  38.            fmt.Println( "net failed",err )
  39.         }
  40.         err = os.MkdirAll( *syncFold , 0755)
  41.         if err != nil{
  42.            fmt.Println( err )
  43.         }
  44.         fmt.Println( "Start Service" )
  45.         Serve( l )
  46.      }else{  
  47.         destination:=fmt.Sprintf( "%s:%s",*syncHost,*listenPort )
  48.         clientSend( *syncFile,destination)
  49.      }
  50. }
  51.  
  52. func clientSend(files string,destination string){
  53.     fInfo:=getFileInfo( files)
  54.     newName :=fmt.Sprintf( "%s",fInfo.fName)
  55.     cmdLine:=  fmt.Sprintf( "upload %s %d %d %d %s " ,newName,fInfo.fMtime.Unix(),fInfo.fPerm,fInfo.fSize,fInfo.fMd5)
  56.     cn,err:=net.Dial( "tcp", destination)
  57.     if err !=nil {
  58.         fmt.Println( "connect error",err )
  59.         return
  60.     }
  61.     defer cn.Close()
  62.     cn.Write( []byte( cmdLine ) )
  63.     cn.Write( []byte( "\r\n" ) )
  64.     fileHandle,err := os.Open( files )
  65.     if err != nil {
  66.         fmt.Println("open ERROR",err)
  67.         return
  68.     }
  69.     io.Copy( cn,fileHandle)
  70.     for{
  71.         buffer :=make( []byte,1024)
  72.         num,err := cn.Read(buffer)
  73.         if err == nil && num > 0{
  74.             fmt.Println(  string(buffer[ :num ]) )
  75.             break
  76.         }
  77.     }
  78. }
  79.  
  80. func getFileInfo( filename string) *sysFileInfo{
  81.     fi,err:= os.Lstat( filename )
  82.     if err != nil {
  83.         fmt.Println("info ERROR",err)
  84.         return nil
  85.     }
  86.     fileHandle,err := os.Open( filename )
  87.     if err != nil {
  88.         fmt.Println("open ERROR",err)
  89.         return nil
  90.     }
  91.  
  92.     h := md5.New()
  93.     _,err = io.Copy( h,fileHandle )
  94.     fileInfo := & sysFileInfo {
  95.         fName : fi.Name(),
  96.         fSize : fi.Size(),
  97.         fPerm : fi.Mode().Perm(),
  98.         fMtime: fi.ModTime(),
  99.         fType : fi.IsDir(),
  100.         fMd5  : fmt.Sprintf( "%x", h.Sum( nil )),
  101.     }
  102.         return fileInfo
  103. }
  104.  
  105. func Serve( l net.Listener) {
  106.     for{
  107.         conn,err := l.Accept()
  108.         if err != nil{
  109.             if ne,ok := err.( net.Error );ok && ne.Temporary(){
  110.                 continue
  111.             }
  112.             fmt.Println( "network error",err )
  113.         }
  114.         go Handler(conn)
  115.     }
  116. }
  117.  
  118. func Handler( conn net.Conn) {
  119.     defer conn.Close()
  120.     state := 0
  121.     var cmd *sysFileInfo
  122.     var fSize int64
  123.     var tempFileName string
  124.     var n int64
  125.     for {
  126.         buffer :=make( []byte,2048)
  127.         num,err := conn.Read(buffer)
  128.         numLen:=int64( num )
  129.         if err != nil && err != io.EOF {
  130.             fmt.Println( "cannot read",err )
  131.         }
  132.         n=0
  133.         if state  == 0 {
  134.             n,cmd = cmdParse( buffer[:num] )
  135.             tempFileName = fmt.Sprintf( "%s.newsync",cmd.fName)
  136.             fSize = cmd.fSize
  137.             state = 1
  138.         }
  139.         if state == 1 {
  140.             last := numLen
  141.             if fSize <= numLen-n {
  142.                 last = fSize + n
  143.                 state = 2
  144.             }
  145.             err = writeToFile( buffer[int( n ):int( last )],tempFileName,cmd.fPerm )
  146.             if err != nil{
  147.                 fmt.Println( "read num error : ",err )
  148.             }
  149.             fSize -=last-n
  150.             if state == 2{
  151.                 os.Remove( cmd.fName)
  152.                 err = os.Rename( tempFileName,cmd.fName)
  153.                 if err != nil{
  154.                     fmt.Println( "rename ",tempFileName," to ",cmd.fName," failed" )
  155.                 }
  156.                 err = os.Chtimes( cmd.fName,time.Now(),cmd.fMtime )
  157.                 if err != nil{
  158.                     fmt.Println( "change the mtime error ",err )
  159.                 }
  160.                 fileHandle,err := os.Open( cmd.fName)
  161.                 if err != nil {
  162.                     fmt.Println("open ERROR",err)
  163.                 }
  164.                 h := md5.New()
  165.                 io.Copy( h,fileHandle )
  166.                 newfMd5 := fmt.Sprintf( "%x", h.Sum( nil ))
  167.                 if newfMd5 == cmd.fMd5{
  168.                     sendInfo:=fmt.Sprintf("%s sync success",cmd.fName)
  169.                     conn.Write([]byte(sendInfo))
  170.                 }else{
  171.                     sendInfo:=fmt.Sprintf("%s sync failed",cmd.fName)
  172.                     conn.Write([]byte(sendInfo))
  173.                 }
  174.             }
  175.         }
  176.     }
  177. }
  178.  
  179. func cmdParse( infor []byte) ( int64 , *sysFileInfo) {
  180.     var i int64
  181.     for i=0;i<int64(len(infor));i++ {
  182.        if infor[i] == '\n' && infor[i-1]  == '\r' {
  183.            cmdLine:=strings.Split( string( infor[:i-1] ) ," ")
  184.            fileName := fmt.Sprintf( "%s/%s",*syncFold,cmdLine[ 1 ] )
  185.            filePerm, _ := strconv.Atoi( cmdLine[ 3 ])
  186.            fileMtime,_:= strconv.ParseInt( cmdLine[ 2 ],10,64 )
  187.            fileSize,_:= strconv.ParseInt( cmdLine[ 4 ],10,64)
  188.            fileInfo := & sysFileInfo {
  189.                 fName : fileName,
  190.                 fMtime: time.Unix( fileMtime,0 ),
  191.                 fPerm : os.FileMode(filePerm),
  192.                 fSize : fileSize,
  193.                 fMd5  : string(cmdLine[ 5 ]),
  194.            }
  195.            return i+1,fileInfo
  196.        }
  197.     }
  198.        return 0,nil
  199. }
  200.  
  201. func writeToFile( data []byte ,fileName string,perm os.FileMode)  error{
  202.     writeFile,err := os.OpenFile( fileName,os.O_RDWR | os.O_APPEND | os.O_CREATE ,perm)
  203.     if err != nil{
  204.         fmt.Println( "write file error:",err )
  205.         return err
  206.     }
  207.     defer writeFile.Close()
  208.     _,err = writeFile.Write( data )
  209.     if err != nil{
  210.        fmt.Println( "write file error",err )
  211.        return err
  212.     }
  213.     return nil
  214. }
  215.  
  216.  
  217. //go/5640

回复 "Golang:gosync 简单文件同步 Simple File Sync "

这儿你可以回复上面这条便签

captcha