C# TCP音乐下载客户端无法获取正确文件大小问题排查
TCP服务器-客户端音乐下载文件大小读取错误排查
我用C#开发基础的TCP服务器-客户端音乐下载应用,当前处于最后一步:服务器向客户端传输MP3文件时,先发送文件大小,再以1024字节分块发送文件内容。但客户端始终无法获取正确的文件大小,得到的数值类似193445465,而真实文件大小应为805KB。以下是客户端与服务器的代码,请求排查问题:
客户端代码
private void server1Download_Click(object sender, EventArgs e) { NetworkStream stream = server.GetStream(); string download_song = searchBar.Text; byte[] buffer = Encoding.ASCII.GetBytes("send4thisclient " + download_song); stream.Write(buffer, 0, buffer.Length); searchBar.Clear(); stream.Flush(); Task.Run(() => { downloadMusic(download_song); }); } private void downloadMusic(string download_song) { NetworkStream stream = server.GetStream(); // Read the file size byte[] fileSizeBytes = new byte[2 * 2]; stream.Read(fileSizeBytes, 0, fileSizeBytes.Length); int fileSize = BitConverter.ToInt32(fileSizeBytes, 0); // Read the file data byte[] fileData = new byte[fileSize]; int bytesReadFileData; int totalBytesRead = 0; while (totalBytesRead < fileSize && (bytesReadFileData = stream.Read(fileData, totalBytesRead, fileSize - totalBytesRead)) > 0) { totalBytesRead += bytesReadFileData; } // Save the downloaded file string currentFolder = Environment.CurrentDirectory; string filePath = Path.Combine(currentFolder, download_song); File.WriteAllBytes(filePath, fileData); MessageBox.Show("downloaded"); }
服务器代码
if (message.StartsWith("send4thisclient")) { string[] list = message.Split(" "); string sName = list[1]; string currentDirectory = Directory.GetCurrentDirectory(); string file = Path.Combine(currentDirectory, sName); using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) { // Get the file size long fileSize = fileStream.Length; byte[] fileSizeBytes = BitConverter.GetBytes(fileSize); // Send file size to client stream.Write(fileSizeBytes, 0, fileSizeBytes.Length); // Send file data to client in chunks byte[] buffers = new byte[1024]; int bytesRead2; while ((bytesRead2 = fileStream.Read(buffers, 0, buffers.Length)) > 0) { stream.Write(buffers, 0, bytesRead2); } } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); }
问题排查与修复
核心问题点
- 数据长度不匹配:服务器端用
long类型存储文件大小(对应8字节),生成的字节数组也是8字节;但客户端仅分配4字节数组(new byte[2*2]),还用BitConverter.ToInt32解析,导致读取字节不全,解析出错误数值。 - 未保证完整读取:
NetworkStream.Read()无法确保一次读取到指定长度字节,必须循环读取直到获取足够数据,当前客户端直接调用一次Read可能拿不到完整的文件大小。
修正后的客户端代码
private void downloadMusic(string download_song) { NetworkStream stream = server.GetStream(); // 读取文件大小:long类型对应8字节 byte[] fileSizeBytes = new byte[sizeof(long)]; int bytesRead = 0; // 循环读取直到拿到完整的8字节 while (bytesRead < fileSizeBytes.Length) { int read = stream.Read(fileSizeBytes, bytesRead, fileSizeBytes.Length - bytesRead); if (read == 0) { MessageBox.Show("连接中断,无法获取文件大小"); return; } bytesRead += read; } // 解析为long类型 long fileSize = BitConverter.ToInt64(fileSizeBytes, 0); // 读取文件内容 byte[] fileData = new byte[fileSize]; int totalBytesRead = 0; while (totalBytesRead < fileSize && (bytesRead = stream.Read(fileData, totalBytesRead, (int)Math.Min(1024, fileSize - totalBytesRead))) > 0) { totalBytesRead += bytesRead; } // 保存文件 string currentFolder = Environment.CurrentDirectory; string filePath = Path.Combine(currentFolder, download_song); File.WriteAllBytes(filePath, fileData); MessageBox.Show("下载完成"); }
补充说明
- 服务器端代码无需修改,
fileStream.Length返回long类型,生成的字节数组长度正确。 - 若需跨不同字节序的平台,可通过
BitConverter.IsLittleEndian判断后调整字节顺序,同一Windows环境下一般无需额外处理。
内容的提问来源于stack exchange,提问作者aaron swartz
相关产品推荐
相关产品推荐

