C#实战027:socket实现大文件传输

 时间:2024-09-28 07:26:54

前面写了一个单文件传输的,后来发现当传送的文件大于设置的缓存空间时,文件就会出现丢包的现象,导致文件无法使用,所以为了适应大文件的传输,这里我将代码进行了下修改,实现大文件传输。

C#实战027:socket实现大文件传输

工具/原料

C#

方法/步骤

1、socket实现大文件传输有个缺点,由于传输过程是通过字节缓存发送,接受也是读写字节,导致整个传输过程效率不高,我尝试了一个169MB的视频文件传输,虽然传完了,但是耗时将近1小时,所以socket在文件传输上还是比较低效的,不建议使用socket进行大文件传送。

C#实战027:socket实现大文件传输

2、因为计算机缓存有限,所以不可能开启太大的缓存来缓存数据的,所以当我们要发送文件较大的文件时我们就要进行分段处理,分段读取,分段发送保存。大家可以看到我们的两个窗口都是同步的,一遍在读取中,一遍就在写入中。如此反复的使用同一块缓存进行数据传递。

3、首先我们先进行循环读取文件信息,这里有个重要的就是做好标记,之前写C#实战026:socket实现单文件传输时就有提到,通过在第一个字节做标记来区分我们传送的信息是什么信息,这个规则自己定义,只要客户端和服务端同步即可这里我们把0定义成信息发送,1定义成文件发送,2定义成文件头信息发送

C#实战027:socket实现大文件传输

4、首先我们先需要凸鹣沮北把我们要发送的文件信息抛给服务器,这里主要需要文件的文件名和文件大小,这里我们只要在用文件流读取文件的时候将这些数据提取出来即可://1缕计瓤账.第一步:发送一个文件,表示文件名和长度,让客户端知道文件大小stringfileName=Path.GetFileName(filePath);//提取文件名Console.WriteLine("发送的文件名是:"+fileName);//查看获取文件名是否正确longfileLength=fsRead.Length;//获取文件长度Console.WriteLine("发送的文件长度为:"+fileLength);//查看文件长度是否正确stringtotalMsg=string.Format("{0}-{1}",fileName,fileLength);//将文件名和文件长度存入一条数据中byte[]buffer=Encoding.UTF8.GetBytes(totalMsg);//将字符串转换成字节数组byte[]newBuffer=newbyte[buffer.Length+1];//新建字节数组,增加一个字节空间newBuffer[0]=2;//将第一个字节标记成2,代表为文件头信息Buffer.BlockCopy(buffer,0,newBuffer,1,buffer.Length);//偏移复制字节数组socketClient.Send(newBuffer);//发送文件文件名和长度发过去

C#实战027:socket实现大文件传输

5、既然是循环写入,我们就要记录当前文件的数据大小和已读取的数据信息,这样循环才有终点,定义一个5M缓存区。byte[]Filebuffer=newbyte[1024*1024*5];//定义5MB的缓存空间(1024字节(b)=1千字节(kb))intreadLength=0;//定义读取的长度boolfirstRead=true;//定义首次读取的状态longsentFileLength=0;//定义发送的长度

C#实战027:socket实现大文件传输

6、接下里解释对文件进行分包发送了,这里唯一要注意的就是第一次发送的时候要为文件价格标记,也就是第一个数据包前加标记,这样服务端才好去识别该数据是什么数据,然后做对应的处理。

7、while(readLength>0争犸禀淫&&sentFileLength<fileLength){se荏鱿胫协ntFileLength+=readLength;//计算已读取文件大小//第一次发送的字节流上加个前缀1if(firstRead){byte[]firstBuffer=newbyte[readLength+1];//这个操作同样也是用来标记文件的firstBuffer[0]=1;//将第一个字节标记成1,代表为文件Buffer.BlockCopy(buffer,0,firstBuffer,1,readLength);//偏移复制字节数组socketClient.Send(firstBuffer,0,readLength+1,SocketFlags.None);Console.WriteLine("第一次读取数据成功,在前面添加一个标记");//发送文件数据包firstRead=false;//切换状态,避免再次进入continue;}socketClient.Send(buffer,0,readLength,SocketFlags.None);//继续发送剩下的数据包Console.WriteLine("{0}:已发送数据:{1}/{2}",socketClient.RemoteEndPoint,sentFileLength,fileLength);//查看发送进度}fsRead.Close();//关闭文件流

C#实战027:socket实现大文件传输

8、接下来在可以在服务端来接受数据了,同样在处理数据的时候要把第一次数据分开,因为第一组数据中添加一个标记符,所以我们在写数据的时候要截取标记后面的数据。

9、if(buffer职邗珩垃[0]==1)//1对应文件信息{SaveFileDialogsfDialog=newSaveFil髫潋啜缅eDialog();//创建SaveFileDialog实例stringspath=@"C:\Users\admin\Desktop";//制定存储路径stringsavePath=Path.Combine(spath,recStr);//获取存储路径及文件名intrec=0;//定义获取接受数据的长度初始值longrecFileLength=0;boolfirstWrite=true;using(FileStreamfs=newFileStream(savePath,FileMode.Create,FileAccess.Write)){while(recFileLength<fileLength){if(firstWrite){fs.Write(buffer,1,firstRcv-1);//截取字节数据写入文件中fs.Flush();//清空缓存信息recFileLength+=firstRcv-1;//记录已获取的数据大小firstWrite=false;//切换状态}else{rec=socketServer.Receive(buffer);//继续接收文件并存入缓存fs.Write(buffer,0,rec);//将缓存中的数据写入文件中fs.Flush();//清空缓存信息recFileLength+=rec;//继续记录已获取的数据大小}Console.WriteLine("{0}:已接收数据:{1}/{2}",socketServer.RemoteEndPoint,recFileLength,fileLength);//查看已接受数据进度}fs.Close();}Console.WriteLine("保存成功!!!!");}

C#实战027:socket实现大文件传输

word怎样开启VBA功能 matlab怎么打包成exe安装程序 如何在DXP中放置有极性电容? NI LabVIEW 2018怎么关闭显示前面板控件提示框 TEKTRONIX AFG310信号发生器使用说明
热门搜索
床上螨虫咬的症状图片 lol图标 草地图片 中国移动图标 美女图片mm131