Client端:
#region 多文件傳輸
public class FileMetadata
{public string FileName { get; set; }public long FileSize { get; set; }
}class Program
{const int PORT = 8888;const int BUFFER_SIZE = 60 * 1024 * 1024;//15s-50 25s-64 33s-32 27s-50 31s-40 25s-60const int MAX_CHANNEL_CAPACITY = 1000;static async Task Main(){Console.WriteLine($"Client ready to send file ...");Stopwatch stopwatch = new Stopwatch();stopwatch.Start();var folderPath = @"D:\cuda";//"D:\TestImage\imagesbaiyou";await SendFolderAsync(folderPath, "192.168.10.147");stopwatch.Stop();Console.WriteLine($"Client Transfer file need {TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds)} Milliseconds");Console.ReadKey();}static async Task SendFolderAsync(string folderPath, string server){using var client = new TcpClient();await client.ConnectAsync(server, PORT);using var stream = client.GetStream();int i = 1;foreach (var filePath in Directory.GetFiles(folderPath)){await SendFileAsync(filePath, stream);Console.WriteLine($"Send file {i++} ...");}}static async Task SendFileAsync(string filePath, NetworkStream stream){var fileInfo = new FileInfo(filePath);var metadata = new FileMetadata{FileName = fileInfo.Name,FileSize = fileInfo.Length};// 發送元數據var metaJson = JsonSerializer.Serialize(metadata);var metaBytes = Encoding.UTF8.GetBytes(metaJson);await stream.WriteAsync(BitConverter.GetBytes(metaBytes.Length));await stream.WriteAsync(metaBytes);// 創建傳輸通道var channel = Channel.CreateBounded<byte[]>(MAX_CHANNEL_CAPACITY);var readTask = FileToChannelAsync(filePath, channel.Writer);var sendTask = ChannelToNetworkAsync(channel.Reader, stream);await Task.WhenAll(readTask, sendTask);}static async Task FileToChannelAsync(string path, ChannelWriter<byte[]> writer){await using var fs = new FileStream(path, FileMode.Open);var buffer = new byte[BUFFER_SIZE];int bytesRead;while ((bytesRead = await fs.ReadAsync(buffer)) > 0){var chunk = new byte[bytesRead];Buffer.BlockCopy(buffer, 0, chunk, 0, bytesRead);await writer.WriteAsync(chunk);}writer.Complete();}static async Task ChannelToNetworkAsync(ChannelReader<byte[]> reader, NetworkStream stream){await foreach (var chunk in reader.ReadAllAsync()){await stream.WriteAsync(BitConverter.GetBytes(chunk.Length));await stream.WriteAsync(chunk);}}
}#endregion
Server端:
#region 多文件傳輸2/*優化性能 7.7GB 文件 平均時間約15s完成接受和傳送傳輸時間和硬盤讀寫速度以及網絡硬件成正比關系測試該電腦本地傳輸速度約15s,固態硬盤將其傳輸到2.0的U盤當中,傳輸573MB的圖像約46s時間, 和單圖直接拷貝的時間差不多±1s的時間*/public class FileMetadata{public string FileName { get; set; }public long FileSize { get; set; }}class Program{const int PORT = 8888;const string SAVE_DIR = @"C:\Users\Leio\Desktop\ServerDownloads";const int BUFFER_SIZE = 1024 * 1024;const int MAX_CHANNEL_CAPACITY = 1000;static Stopwatch stopwatch = new Stopwatch();static async Task Main(){Directory.CreateDirectory(SAVE_DIR);var listener = new TcpListener(IPAddress.Any, PORT);listener.Start();Console.WriteLine("Server started,waiting client connect ...");while (true){var client = await listener.AcceptTcpClientAsync();_ = ProcessClientAsync(client);}}static async Task ProcessClientAsync(TcpClient client){stopwatch.Restart();using (client)using (var stream = client.GetStream()){try{while (true){// 讀取元數據var metaSize = BitConverter.ToInt32(await ReadExactlyAsync(stream, 4));var metadata = JsonSerializer.Deserialize<FileMetadata>(Encoding.UTF8.GetString(await ReadExactlyAsync(stream, metaSize)));// 創建傳輸通道var channel = Channel.CreateBounded<byte[]>(MAX_CHANNEL_CAPACITY);var savePath = Path.Combine(SAVE_DIR, metadata.FileName);// 啟動并行任務var receiveTask = ReceiveFileDataAsync(stream, channel.Writer, metadata.FileSize);var saveTask = SaveFileAsync(channel.Reader, savePath);await Task.WhenAll(receiveTask, saveTask);Console.WriteLine($"File saved: {savePath}");//totalTime += stopwatch.ElapsedMilliseconds;}}catch (EndOfStreamException){Console.WriteLine("Connection closed by client");}}stopwatch.Stop();Console.WriteLine($"Client Transfer file need {TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds)} s");}static async Task ReceiveFileDataAsync(NetworkStream stream,ChannelWriter<byte[]> writer,long totalSize){try{long remaining = totalSize;while (remaining > 0){var chunkSize = BitConverter.ToInt32(await ReadExactlyAsync(stream, 4));var chunkData = await ReadExactlyAsync(stream, chunkSize);await writer.WriteAsync(chunkData);remaining -= chunkSize;}}finally{writer.Complete();}}static async Task SaveFileAsync(ChannelReader<byte[]> reader, string savePath){await using var fs = new FileStream(savePath, FileMode.Create);await foreach (var chunk in reader.ReadAllAsync()){await fs.WriteAsync(chunk);}}static async Task<byte[]> ReadExactlyAsync(NetworkStream stream, int count){var buffer = new byte[count];int totalRead = 0;while (totalRead < count){var read = await stream.ReadAsync(buffer, totalRead, count - totalRead);if (read == 0) throw new EndOfStreamException();totalRead += read;}return buffer;}}#endregion