@(go語言 黑馬)[GO語言]
通過TCP通信完成兩端的文件傳輸
- 題目:分別搭建好文件的發(fā)送端和接收端
- 知識點:TCP通信
- 邏輯思路(詳細的步驟在代碼注釋中):
_1. 發(fā)送端 將文件名發(fā)送給 接收端
_2. 接收端 收到文件名后塞蹭,發(fā)送 "ok" 信號給 發(fā)送端
_3. 發(fā)送端 收到 "ok" 信號后吗跋,開始傳輸文件內(nèi)容給 接收端
_4. 接收端 接收并保存文件內(nèi)容
- 接收端代碼如下:
package main
import "fmt"
func main() {
receiver()
}
func receiver() {
//建立TCP通信的IP+port
listener,err:=net.Listen("tcp","127.0.0.1:8008")
if err!=nil{
fmt.Println("net.Listen err:",err)
return
}
defer listener.Close()//不要忘記關(guān)閉
conn,err:=listener.Accept()//創(chuàng)建用于通信的socket
if err!=nil{
fmt.Println("listener.Accept err:",err)
return
}
defer conn.Close()//不要忘記關(guān)閉
buf:=make([]byte,4096)
n,err:=conn.Read(buf)//接收發(fā)送端發(fā)來的文件名
if err!=nil{
fmt.Println("conn.Read err:",err)
return
}
filmname:=string(buf[:n])//轉(zhuǎn)成字符串
conn.Write([]byte("ok"))//回發(fā)“ok”信號給客戶端
receiveFilm(filmname,conn)//接收和保存文件由該函數(shù)來完成
}
func receiveFilm(filmname string,conn net.Conn) {
fl,err:=os.Create("C:\\Users\\shalom\\Desktop\\test\\"+filmname)//創(chuàng)建新文件(需要指定 保存路徑 和 文件名)
if err!=nil{
fmt.Println("os.Create err:",err)
return
}
defer fl.Close()//不要忘記關(guān)閉
buf:=make([]byte,4096)
for {//conn是一個文件啄骇,里面緩存了發(fā)送端發(fā)送的所有內(nèi)容,所以需要用for循環(huán)來判斷是否讀完
n, err := conn.Read(buf)//讀取到buf緩沖區(qū)中
if err != nil {
if err==io.EOF{//io.EOF是文件末尾哑姚,當(dāng)err讀到它,代表已經(jīng)讀完
fmt.Println("文件讀完畢!")
}else {
fmt.Println("conn.Read err:", err)
}
return
}
fl.Write(buf[:n])//把讀到的內(nèi)容寫到新創(chuàng)建的文件中专缠,讀多少寫多少
}
}
- 發(fā)送端代碼如下:
package main
import "fmt"
func main() {
sender()
}
func sender() {
//fmt.Println("請輸入需要發(fā)送文件的絕對路徑:")
/*path:=make([]byte,4096)
n,err:=os.Stdin.Read(path)
if err!=nil{
fmt.Println("os.Stdin.Read err:",err)
return
}
filmpath:=string(path[:n])*/
list:=os.Args//讀取命令行狰挡,返回的是一個字符串切片捂龄,list[0] = "go run xxx.go" list[1] = "要發(fā)送的文件的絕對路徑“
filmpath:=string(list[1])//文件絕對路徑轉(zhuǎn)成字符串
filmInfo,err:=os.Stat(filmpath)//通過stat函數(shù)得到文件屬性(Name,Size ...)
if err!=nil{
fmt.Println("os.Stat err:",err)
return
}
fileName:=filmInfo.Name()//獲得文件名
conn,err:=net.Dial("tcp","127.0.0.1:8008")//與接收端建立TCP連接
if err!=nil{
fmt.Println("net.Dial err:",err)
return
}
defer conn.Close()//不要忘記關(guān)閉
conn.Write([]byte(fileName))//把文件名發(fā)送給接收端
buf:=make([]byte,16)
n,err:=conn.Read(buf)//接收"ok"信號
if err!=nil{
fmt.Println("conn.Read err:",err)
return
}
if string(buf[:n])=="ok"{//如果是"ok",則發(fā)送文件內(nèi)容
sendfilm(filmpath,conn)//將文件的絕對路徑傳入加叁,不是文件名
}
}
func sendfilm(filmpath string,conn net.Conn) {
fl,err:=os.Open(filmpath)//打開文件
if err!=nil{
fmt.Println("os.Open err:",err)
return
}
defer fl.Close()
buf:=make([]byte,4096)
for {
n,err:=fl.Read(buf)//讀取到緩沖區(qū)
if err!=nil{
if err==io.EOF{ //判斷是否讀完
fmt.Println("文件發(fā)送完畢倦沧!")
}else {
fmt.Println("fl.Read err:", err)
}
return
}
conn.Write(buf[:n])//發(fā)送文件內(nèi)容給接收端
}
}