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