GO语言初级学习之代码案例11 (TCP通信 之 “文件传输”)
2018-08-18 本文已影响21人
大爬虫Shalom
@(go语言 黑马)[GO语言]
通过TCP通信完成两端的文件传输
- 题目:分别搭建好文件的发送端和接收端
- 知识点:TCP通信
- 逻辑思路(详细的步骤在代码注释中):
_1. 发送端 将文件名发送给 接收端
_2. 接收端 收到文件名后,发送 "ok" 信号给 发送端
_3. 发送端 收到 "ok" 信号后,开始传输文件内容给 接收端
_4. 接收端 接收并保存文件内容
- 接收端代码如下:
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()//不要忘记关闭
conn,err:=listener.Accept()//创建用于通信的socket
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
}
filmname:=string(buf[:n])//转成字符串
conn.Write([]byte("ok"))//回发“ok”信号给客户端
receiveFilm(filmname,conn)//接收和保存文件由该函数来完成
}
func receiveFilm(filmname string,conn net.Conn) {
fl,err:=os.Create("C:\\Users\\shalom\\Desktop\\test\\"+filmname)//创建新文件(需要指定 保存路径 和 文件名)
if err!=nil{
fmt.Println("os.Create err:",err)
return
}
defer fl.Close()//不要忘记关闭
buf:=make([]byte,4096)
for {//conn是一个文件,里面缓存了发送端发送的所有内容,所以需要用for循环来判断是否读完
n, err := conn.Read(buf)//读取到buf缓冲区中
if err != nil {
if err==io.EOF{//io.EOF是文件末尾,当err读到它,代表已经读完
fmt.Println("文件读完毕!")
}else {
fmt.Println("conn.Read err:", err)
}
return
}
fl.Write(buf[:n])//把读到的内容写到新创建的文件中,读多少写多少
}
}
- 发送端代码如下:
package main
import "fmt"
func main() {
sender()
}
func sender() {
//fmt.Println("请输入需要发送文件的绝对路径:")
/*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] = "要发送的文件的绝对路径“
filmpath:=string(list[1])//文件绝对路径转成字符串
filmInfo,err:=os.Stat(filmpath)//通过stat函数得到文件属性(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()//不要忘记关闭
conn.Write([]byte(fileName))//把文件名发送给接收端
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",则发送文件内容
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)//读取到缓冲区
if err!=nil{
if err==io.EOF{ //判断是否读完
fmt.Println("文件发送完毕!")
}else {
fmt.Println("fl.Read err:", err)
}
return
}
conn.Write(buf[:n])//发送文件内容给接收端
}
}