file-server

package main

import (
    "bufio"
    "encoding/binary"
    "fmt"
    "net"
    "os"
    "unsafe"
)

func SHandleError(err error, when string)  {
    if err != nil{
        if  when == "conn.Read" {
           fmt.Println("读取客户端数据异常,客户端断开")
        }else{
        fmt.Println("服务端异常退出,err=", err, when)
        os.Exit(1)
        }
    }
}

func BytesToInt64(buf []byte) int64 {
    return int64(binary.BigEndian.Uint64(buf))
}
func HandleConn(conn net.Conn) {
    defer func() {
        conn.Close()
        fmt.Printf("已断开与%v的链接\n", conn.RemoteAddr())
    }()
    //接受客户端发来的要传文件大小
    buffer2 := make([]byte, 10)
    m, e := conn.Read(buffer2)
    SHandleError(e, "listener.Accept")
    //[]byte转换为int64
    i := BytesToInt64(buffer2[:m])
    //int64转换为int
    j := *(*int)(unsafe.Pointer(&i))
    fmt.Printf("%d, %T\n",j,j)
 
    //接受客户端发来的要传文件名称字符串
    buffer3 := make([]byte, 1000)
    m1, _ := conn.Read(buffer3)
    fmt.Printf("%s \n",buffer3[:m1])
    fmt.Printf(string(buffer3[:m1]))

    dstFile, e := os.OpenFile(string(buffer3[:m1]), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
    writer := bufio.NewWriter(dstFile)
    defer dstFile.Close()
    buffer := make([]byte, 512)
    total := 0

    for {
        //接受客户端上传的文件
        n, e := conn.Read(buffer)
        if e != nil {
          fmt.Println("读取客户端数据异常,客户端断开")
          break
        }
        total += n
        //写入服务端本地文件
        writer.Write(buffer[:n])
        writer.Flush()
        fmt.Printf("成功写入%d字节, 共%d字节, 进度 %d \n", n, total, 100*total/j)
        //如果实际总接受字节数与客户端给的要传输字节数相等,说明传输完毕
        if total == j{
            fmt.Println("文件接受成功,共",total,"字节: ", string(buffer3[:m1]))
            //回复客户端已收到文件
            conn.Write([]byte("文件接受成功"))
            break
        }
    }
}

func main() {
    listen, e := net.Listen("tcp", "0.0.0.0:8081")
    SHandleError(e, "net.Listen")
    defer func() {
        listen.Close()
        fmt.Println("服务端正常退出")
    }()
    for {
        conn, err := listen.Accept()
        if err != nil {
            fmt.Println(err)
            continue   // 继续监听
        }
        go HandleConn(conn)
    }
}
posted @ 2022-10-21 12:48  yangxl-dev  阅读(56)  评论(0)    收藏  举报