文章目錄
-
-
- 網絡檔案傳輸:
- 檔案傳輸——發送端(用戶端):
- 檔案傳輸——接收端(伺服器):
網絡檔案傳輸:
指令行參數: 在main函數啟動時,向整個程式傳參。
文法: go run xxx.go argv1 argv2 argv3 argv4
xxx.go: 第 0 個參數。
argv1 :第 1 個參數。
argv2 :第 2個參數。
argv3 :第 3 個參數。
argv4 :第 4 個參數。
使用: list := os.Args
參數3 = list[3]
擷取檔案屬性:
fileInfo:os.stat(檔案通路絕對路徑)
fileInfo 接口,兩個接口。
Name() 擷取檔案名。
Size() 擷取檔案大小。
func main() {
list := os.Args // 擷取指令行參數
if len(list) != 2 {
fmt.Println("格式為:go run xxx.go 檔案名")
return
}
// 提取檔案名
path := list[1]
// 擷取檔案屬性
fileInfo, err := os.Stat(path)
if err != nil {
fmt.Println("os.Stat err:", err)
return
}
fmt.Println("檔案名:", fileInfo.Name())
fmt.Println("檔案大小:", fileInfo.Size())
}
檔案傳輸——發送端(用戶端):
1. 提示使用者使用指令行參數輸入檔案名。接收檔案名 filepath(含通路路徑)
2. 使用 os.Stat()擷取檔案屬性,得到純檔案名 fileName(去除通路路徑)
3. 主動發起連接配接伺服器請求,結束時關閉連接配接。
4. 發送檔案名到接收端 conn.Write()
5. 讀取接收端回發的确認資料 conn.Read()
6. 判斷是否為“ok”。如果是,封裝函數 SendFile() 發送檔案内容。傳參 filePath 和 conn
7. 隻讀 Open 檔案, 結束時Close檔案
8. 循環讀本地檔案,讀到 EOF,讀取完畢。
9. 将讀到的内容原封不動 conn.Write 給接收端(伺服器)
func sendFile(conn net.Conn, filePath string) {
// 隻讀打開檔案
f, err := os.Open(filePath)
if err != nil {
fmt.Println("os.Open err:", err)
return
}
defer f.Close()
// 從本檔案中,讀資料,寫給網絡接收端。 讀多少,寫多少。原封不動。
buf := make([]byte, 4096)
for {
n, err := f.Read(buf)
if err != nil {
if err == io.EOF {
fmt.Println("發送檔案完成。")
} else {
fmt.Println("os.Open err:", err)
}
return
}
// 寫到網絡socket中
_, err = conn.Write(buf[:n])
if err != nil {
fmt.Println("conn.Write err:", err)
return
}
}
}
func main() {
list := os.Args // 擷取指令行參數
if len(list) != 2 {
fmt.Println("格式為:go run xxx.go 檔案絕對路徑")
return
}
// 提取 檔案的絕對路徑
filePath := list[1]
//提取檔案名
fileInfo, err := os.Stat(filePath)
if err != nil {
fmt.Println("os.Stat err:", err)
return
}
fileName := fileInfo.Name()
// 主動發起連接配接請求
conn, err := net.Dial("tcp", "127.0.0.1:8008")
if err != nil {
fmt.Println("net.Dial err:", err)
return
}
defer conn.Close()
// 發送檔案名給 接收端
_, err = conn.Write([]byte(fileName))
if err != nil {
fmt.Println("conn.Write err:", err)
return
}
// 讀取伺服器回發的 OK
buf := make([]byte, 16)
n, err := conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
if "ok" == string(buf[:n]) {
// 寫檔案内容給伺服器——借助conn
sendFile(conn, filePath)
}
}
檔案傳輸——接收端(伺服器):
1. 建立監聽 listener,程式結束時關閉。
2. 阻塞等待用戶端連接配接 conn,程式結束時關閉conn。
3. 讀取用戶端發送檔案名。儲存 fileName。
4. 回發“ok”。
5. 封裝函數 RecvFile 接收用戶端發送的檔案内容。傳參 fileName 和 conn
6. 按檔案名 Create 檔案,結束時 Close
7. 循環 Read 發送端網絡檔案内容,當讀到 0 說明檔案讀取完畢。
8. 将讀到的内容原封不動Write到建立的檔案中
func recvFile(conn net.Conn, fileName string) {
// 按照檔案名建立新檔案
f, err := os.Create(fileName)
if err != nil {
fmt.Println("os.Create err:", err)
return
}
defer f.Close()
// 從 網絡中讀資料,寫入本地檔案
buf := make([]byte, 4096)
for {
n,_ := conn.Read(buf)
if n == 0 {
fmt.Println("接收檔案完成。")
return
}
// 寫入本地檔案,讀多少,寫多少。
f.Write(buf[:n])
}
}
func main() {
// 建立用于監聽的socket
listener, err := net.Listen("tcp", "127.0.0.1:8008")
if err != nil {
fmt.Println(" net.Listen err:", err)
return
}
defer listener.Close()
// 阻塞監聽
conn, err := listener.Accept()
if err != nil {
fmt.Println(" listener.Accept() err:", err)
return
}
defer conn.Close()
// 擷取檔案名,儲存
buf := make([]byte, 4096)
n, err := conn.Read(buf)
if err != nil {
fmt.Println(" conn.Read err:", err)
return
}
fileName := string(buf[:n])
// 回寫 ok 給發送端
conn.Write([]byte("ok"))
// 擷取檔案内容
recvFile(conn, fileName)
}