server端:
package main
import (
"bufio"
"encoding/binary"
"fmt"
"net"
"os"
"unsafe"
)
func SHandleError(err error, when string) {
if err != nil{
fmt.Println("服务端异常退出,err=", err, when)
os.Exit(1)
}
}
func BytesToInt64(buf []byte) int64 {
return int64(binary.BigEndian.Uint64(buf))
}
func main() {
//建立tcp监听
listener, e := net.Listen("tcp", ":8080")
SHandleError(e, "net.Listen")
defer func() {
listener.Close()
fmt.Println("服务端正常退出")
}()
//接受客户端请求,建立会话专线Conn
conn, e := listener.Accept()
SHandleError(e, "listener.Accept")
defer func() {
conn.Close()
fmt.Printf("已断开与%v的链接\n", conn.RemoteAddr())
}()
dstFile, e := os.OpenFile(`meinv1.mp4`, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
writer := bufio.NewWriter(dstFile)
defer dstFile.Close()
buffer := make([]byte, 100)
total := 0
//接受客户端发来的要传文件大小
buffer2 := make([]byte, 10)
m, e := conn.Read(buffer2)
//size := string(buffer2[:m])
//fmt.Printf("%s\n",size)
//i, _ := strconv.Atoi(size)
//[]byte转换为int64
i := BytesToInt64(buffer2[:m])
fmt.Printf("%d, %T\n",i,i)
//int64转换为int
j := *(*int)(unsafe.Pointer(&i))
fmt.Printf("%d, %T\n",j,j)
for {
//接受客户端上传的文件
n, e := conn.Read(buffer)
SHandleError(e, "conn.Read")
total += n
//写入服务端本地文件
writer.Write(buffer[:n])
writer.Flush()
fmt.Printf("成功写入%d个字节,共%d字节\n", n, total)
//如果实际总接受字节数与客户端给的要传输字节数相等,说明传输完毕
if total == j{
fmt.Println("文件接受成功,共",total,"字节")
//回复客户端已收到文件
conn.Write([]byte("文件接受成功"))
break
}
}
}
client端:
package main
import (
"bufio"
"encoding/binary"
"fmt"
"io"
"net"
"os"
"time"
)
/*
·实现tcp文件上传功能
*/
func CHandleError2(err error, when string) {
if err != nil {
fmt.Println("客户端异常退出:err=", err, when)
os.Exit(1)
}
}
func Int64ToBytes(i int64) []byte {
var buf = make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
return buf
}
func main() {
conn, e := net.Dial("tcp", "127.0.0.1:8080")
CHandleError2(e, "net.Dial")
defer func() {
conn.Close()
fmt.Println("客户端正常退出")
}()
//获取目标文件的大小,传给服务端
fileInfo, _ := os.Stat(`perfect.mp4`)
size := fileInfo.Size()
bytes := Int64ToBytes(size)
conn.Write(bytes)
//暂时通过客户端sleep 200毫秒解决粘包问题,还可以通过tcp重连解决,以后再用(包头+数据)封装数据包的方式解决
time.Sleep(time.Millisecond * 200)
buffer := make([]byte, 100)
srcFile, _ := os.Open(`perfect.mp4`)
reader := bufio.NewReader(srcFile)
total := 0
for {
n, err := reader.Read(buffer)
fmt.Println(n, err)
if err == io.EOF{
fmt.Println("文件发送完毕")
fmt.Println(total)
break
}else {
_, e = conn.Write(buffer[:n])
total += n
CHandleError2(e, "conn.Write")
}
}
n, e := conn.Read(buffer)
CHandleError2(e, "conn.Read")
replyMsg := buffer[:n]
fmt.Println("服务端:", string(replyMsg))
}
Go语言网络通信---tcp上传大文件(粘包问题还需优雅解决)
原文:https://www.cnblogs.com/yunweiqiang/p/12735452.html