Go言語ネットワーク通信--- tcpは大きなファイルをアップロードします(スティッキーパケットの問題はエレガントに解決する必要があります)

サーバー側:

パッケージの主な

インポート(
	"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监挺
	リスナー、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( "Link with%v has been disconnected \ 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)

	// []バイトが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、合計)

		//実際の合計受信バイト数がクライアントによって送信されるバイト数と等しい場合、次の
		場合に送信が完了します。合計== j { 
			fmt.Println( "ファイルが正常に受け入れられた、合計"、合計、 "バイト")
			//クライアントがファイルを受け取ったと
			応答conn.Write([]バイト( "ファイルが正常に受け入れられました"))
			ブレーク
		} 
	} 
}

クライアント側:

パッケージのメイン

インポート(
	"bufio" 
	"encoding / binary" 
	"fmt" 
	"io" 
	"net" 
	"os" 
	"time" 

/ * 
・TUTORIAL现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。ダイヤル」) 

	defer func(){ 
		conn.Close() 
		fmt.Println( "クライアントは正常に終了します")
	}()

	//ターゲットファイルのサイズを取得してサーバーに
	渡すfileInfo、_:= os.Stat( `perfect.mp4`)
	size:= fileInfo.Size()
	bytes:= Int64ToBytes(size)
	conn.Write(bytes )

	//スティッキーパケットの問題をクライアントのスリープ200ミリ秒で一時的に解決し、tcp再接続で解決することもできます。後で、(パケットヘッダー+データ)を使用してデータパケットをカプセル化します
	。Time.Sleep(time.Millisecond * 200)

	バッファー:= 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( "File sent completed")
			fmt.Println(total)
			break 
		} else { 
			_、e = conn.Write(バッファ[:n])
			合計+ = n 
			CHandleError2(e、 "conn.Write")
		}
	} 

	n、e:= conn.Read(buffer)
	CHandleError2(e、 "conn.Read")
	replyMsg:= buffer [:n] 
	fmt.Println( "服务端:"、string(replyMsg))
}

  

おすすめ

転載: www.cnblogs.com/yunweiqiang/p/12735452.html