c# socket 文件 传输 进度

wangzhe1945 2008-12-15 03:44:37
c# 用 socket 传输文件时,如何得到当前传输进度?

filestream=new FileStream(filename,FileMode.Open,FileAccess.Read);

byte[] buffer = new byte[1024];

filestream.Seek(0,SeekOrigin.Begin);
while((number=filestream.Read(buffer,0,1024))!=0)
{
stream.Write(buffer,0,number);
stream.Flush();
Console.WriteLine(filestream.Position);
}
filestream.Close();

如果网络繁忙的情况下,以上代码会不会出现问题,写入太快,而对方却无法接收?
...全文
533 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangzhe1945 2008-12-17
  • 打赏
  • 举报
回复
帖子沉了,自己总结下

System.Net.Sockets.NetworkStream
NetworkStream 类提供在阻塞模式下通过 Stream 套接字发送和接收数据的方法。有关阻塞与非阻塞 Socket 的更多信息,请参见使用异步客户端套接字。您可以使用 NetworkStream 类进行同步和异步数据传输。有关异步通信与同步通信的更多信息,请参见套接字。要创建 NetworkStream,必须提供连接的 Socket。也可指定 NetworkStream 对所提供的 Socket 具有哪些 FileAccess 权限。默认情况下,关闭 NetworkStream 并不会关闭所提供的 Socket。如果要使 NetworkStream 拥有关闭所提供的 Socket 的权限,则必须将 ownsSocket 构造函数参数的值指定为 true。

将 Write 和 Read 方法用于简单的单线程同步阻塞 I/O。若要使用不同的线程来处理 I/O,则请考虑使用 BeginWrite/ EndWrite 和 BeginRead/ EndRead 方法进行通信。

NetworkStream 不支持对网络数据流的随机访问。CanSeek 属性用于指示流是否支持查找,它的值始终为 false。读取 Position 属性、读取 Length 属性或者调用 Seek 方法都会引发 NotSupportedException。

公共方法
BeginRead
受 .NET Framework 精简版的支持。
已重写。从 NetworkStream 开始异步读取。
BeginWrite
受 .NET Framework 精简版的支持。
已重写。开始向流异步写入。
Close
受 .NET Framework 精简版的支持。
已重写。关闭 NetworkStream。
CreateObjRef(从 MarshalByRefObject 继承) 创建一个对象,该对象包含生成用于与远程对象进行通讯的代理所需的全部相关信息。
EndRead
受 .NET Framework 精简版的支持。
已重写。处理异步读取的结束。
EndWrite
受 .NET Framework 精简版的支持。
已重写。处理异步写入的结束。
Equals(从 Object 继承)
受 .NET Framework 精简版的支持。
已重载。确定两个 Object 实例是否相等。
Flush
受 .NET Framework 精简版的支持。
已重写。刷新流中的数据。保留此方法供将来使用。
GetHashCode(从 Object 继承)
受 .NET Framework 精简版的支持。
用作特定类型的哈希函数,适合在哈希算法和数据结构(如哈希表)中使用。
GetLifetimeService(从 MarshalByRefObject 继承) 检索控制此实例的生存期策略的当前生存期服务对象。
GetType(从 Object 继承)
受 .NET Framework 精简版的支持。
获取当前实例的 Type。
InitializeLifetimeService(从 MarshalByRefObject 继承) 获取控制此实例的生存期策略的生存期服务对象。
Read
受 .NET Framework 精简版的支持。
已重写。从 NetworkStream 读取数据。
ReadByte(从 Stream 继承)
受 .NET Framework 精简版的支持。
从流中读取一个字节,并将流内的位置向前推进一个字节,或者如果已到达流的末尾,则返回 -1。
Seek
受 .NET Framework 精简版的支持。
已重写。将流的当前位置设置为给定值。此方法始终引发 NotSupportedException。
SetLength
受 .NET Framework 精简版的支持。
已重写。设置流的长度。此方法始终引发 NotSupportedException。
ToString(从 Object 继承)
受 .NET Framework 精简版的支持。
返回表示当前 Object 的 String。
Write
受 .NET Framework 精简版的支持。
已重写。将数据写入 NetworkStream。
WriteByte(从 Stream 继承)
受 .NET Framework 精简版的支持。
将一个字节写入流内的当前位置,并将流内的位置向前推进一个字节。

wangzhe1945 2008-12-16
  • 打赏
  • 举报
回复
还有一个问题,如何知道当前传输的进度呢?
hangang7403 2008-12-15
  • 打赏
  • 举报
回复
up
claymore1114 2008-12-15
  • 打赏
  • 举报
回复
UP
liningln0 2008-12-15
  • 打赏
  • 举报
回复
阻塞是在网络拥挤的时候必然现象,如果要从根本上解决的话很难,如果你现在缓解的话,可以采取多线程和stream.Flush()都有一定的用处.
xu_2007 2008-12-15
  • 打赏
  • 举报
回复
顶一下!
zcandyly20211 2008-12-15
  • 打赏
  • 举报
回复
友情up~
wangzhe1945 2008-12-15
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yhy0611 的回复:]
如果网络繁忙的情况下,以上代码会不会出现问题,写入太快,而对方却无法接收?
=============================================================


绝对会的,我现在正在经历这个问题,像1楼说用缓冲区可以解决,但我的问题太严重了,一个2K的包,可能要延迟十分钟,已经超出了程序控制的范围,正在建议用户把ADSL换成光纤
[/Quote]

是用UDP协议传输的吗?
sikezx 2008-12-15
  • 打赏
  • 举报
回复
while(uiTotal < uiLength)

{

int iEnd=pDlg->m_bSendEnd;

//传送发送端状态(是否结束)

iNumByte = sockSend.Send(&iEnd, sizeof(int));

//发送错误

if(iNumByte == SOCKET_ERROR)

{

AfxMessageBox("发送错误!");

goto ExitLable1;

}else if(iEnd==1)//发送端终止

{

AfxMessageBox("发送端终止");

goto ExitLable1;

}

//读取文件内容

if((int)(uiLength - uiTotal) < iBufSize)

iSize = uiLength - uiTotal;//当小于缓冲区iTEST时的处理

iSize=file.Read(pBuf , iSize);//得到读取的字节数

int iCount=0;

//发送定长文件数据

while(iCount<iSize)

{

iNumByte = sockSend.Send(pBuf, iSize-iCount);//注意iNumByte为实际的发送字节数,不要以iSize为准

if(iNumByte == SOCKET_ERROR)

{

AfxMessageBox("发送错误!");

goto ExitLable1;

}

iCount+=iNumByte;

if(iCount<iSize)

{

file.Seek(iSize-iCount,CFile::current);

}

}

uiTotal += iCount;

//设置发送数据进度条

pDlg->m_CtrlProgressSend.SetPos(int(((double)uiTotal/uiLength)*100));

str.Format("发送进度:%d%%",int(((double)uiTotal/uiLength)*100));

//表明发送数据百分比

pDlg->GetDlgItem(IDC_STATIC_SEND)->GetWindowText(str1);

if(str1!=str)

pDlg->GetDlgItem(IDC_STATIC_SEND)->SetWindowText(str);

}

//发送文件成功

AfxMessageBox("发送文件成功!");

ExitLable1:

delete[] pBuf;

file.Close();

sockSend.Close();

pDlg->m_CtrlProgressSend.SetPos(0);//恢复进度

pDlg->GetDlgItem(IDC_BUTTON_SEND_END)->EnableWindow(FALSE);//设置发送结束按钮禁止

pDlg->GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(TRUE);//设置发送按钮正常

pDlg->GetDlgItem(IDC_STATIC_SEND)->SetWindowText("发送进度:"); //恢复提示进度

return 0;

}

UINT ReceiveDataThread(LPVOID lpParam)

{

CTzg004Dlg *pDlg=(CTzg004Dlg *)lpParam;

//保存文件对话框

CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,

"所有文件 (*.*)|*.*||");

while(dlg.DoModal()!=IDOK)

{

AfxMessageBox("选择文件出错,请重新选择!");

}

CString str,str1,str2;

CSocket sockRecv;

sockRecv.Create();

pDlg->m_CtrlIPSend.GetWindowText(str);//得到发送端IP地址

pDlg->GetDlgItem(IDC_BUTTON_RECEIVE)->EnableWindow(FALSE);//禁止接收按钮

while(sockRecv.Connect(str,pDlg->m_iDataPort2)==0)//连接发送方地址,若上网,可改为实际IP地址,端口要跟Server端相同。

{

Sleep(50);

}

pDlg->GetDlgItem(IDC_BUTTON_REC_END)->EnableWindow(TRUE);//打开终止接收按钮

str2=dlg.GetPathName();//得到文件名

CFile file;

file.Open(str2, CFile::modeCreate | CFile::modeWrite);

BOOL bFileFail=FALSE;

DWORD dwTemp = 0;

sockRecv.AsyncSelect(0);

sockRecv.IOCtl( FIONBIO, &dwTemp);//变为阻塞方式



UINT uiLength;

sockRecv.Receive(&uiLength, 4);//接收发方(Server端)的文件大小

int iBufSize = 1024 * 5;

int iSize = iBufSize;

LPBYTE pBuf = new BYTE[iBufSize];

int iNumByte;

UINT uiTotal = 0;

while(uiTotal < uiLength)

{

int iEnd=0;

//接收端终止

if(pDlg->m_bRecEnd)

{

AfxMessageBox("接收端终止!");

goto ExitLable2;

}

//接收发送端状态数据

iNumByte=sockRecv.Receive(&iEnd, sizeof(int));

if(iNumByte == SOCKET_ERROR)

{

AfxMessageBox("接收信号错误!");

goto ExitLable2;

}

//发送端终止

if(iEnd==1)

{

AfxMessageBox("发送端终止!");

goto ExitLable2;

}



if((int)(uiLength - uiTotal) < iBufSize)

iSize = uiLength - uiTotal;

int iCount=0;

//读取定长数据

while(iCount<iSize)

{

iNumByte = sockRecv.Receive(pBuf, iSize-iCount);

if(iNumByte == SOCKET_ERROR)

{

AfxMessageBox("接收错误!");

goto ExitLable2;

}

iCount+=iNumByte;

file.Write(pBuf, iNumByte);

}

uiTotal += iCount;//以实际接收字节为准

//设置接收进度

pDlg->m_CtrlProgressRec.SetPos(int(((double)uiTotal/uiLength)*100));

str.Format("接收进度:%d%%",int(((double)uiTotal/uiLength)*100));

//显示接收进度百分比

pDlg->GetDlgItem(IDC_STATIC_REC)->GetWindowText(str1);

if(str1!=str)

pDlg->GetDlgItem(IDC_STATIC_REC)->SetWindowText(str);

}

//接收文件成功

AfxMessageBox("接收文件成功!");

bFileFail=TRUE;

ExitLable2:

delete[] pBuf;

file.Close();

//文件接收失败,则删除接收文件

if(!bFileFail)

{

CFile::Remove( str2 );

}

sockRecv.Close();

pDlg->m_CtrlProgressRec.SetPos(0);//恢复接收进度

//禁止终止接收按钮

pDlg->GetDlgItem(IDC_BUTTON_REC_END)->EnableWindow(FALSE);

//打开接收按钮

pDlg->GetDlgItem(IDC_BUTTON_RECEIVE)->EnableWindow(TRUE);

//恢复提示进度

pDlg->GetDlgItem(IDC_STATIC_REC)->SetWindowText("接收进度:");

return 0;

}

看看吧!应该有帮助
sikezx 2008-12-15
  • 打赏
  • 举报
回复
//1:显示文件进度

//2:可以随时终止传输过程

//发送数据线程

UINT SendDataThread(LPVOID lpParam);

//接收数据线程

UINT ReceiveDataThread(LPVOID lpParam);

//发送数据按钮消息响应函数

void CTzg004Dlg::OnButtonSend()

{

// TODO: Add your control notification handler code here

//初始化数据发送结束标志

m_bSendEnd=FALSE;

//初始化数据接收结束标志

m_bRecEnd=FALSE;

//更新对话框数据

UpdateData(TRUE);

//打开文件对话框

CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,

"所有文件 (*.*)|*.*||");

if(dlg.DoModal()==IDOK)

{

m_strFileName=dlg.GetPathName();

//开始发送数据线程

AfxBeginThread(SendDataThread,this,THREAD_PRIORITY_NORMAL);

}

}

//接收数据按钮消息响应函数

void CTzg004Dlg::OnButtonReceive()

{

// TODO: Add your control notification handler code here

//初始化数据发送结束标志

m_bSendEnd=FALSE;

//初始化数据接收结束标志

m_bRecEnd=FALSE;

UpdateData(TRUE);

//开始接收数据线程

AfxBeginThread(ReceiveDataThread,this,THREAD_PRIORITY_NORMAL);

}

//终止发送按钮消息响应

void CTzg004Dlg::OnButtonSendEnd()

{

// TODO: Add your control notification handler code here

//设置发送数据结束标志

m_bSendEnd=TRUE;

}

//终止接收按钮消息响应

void CTzg004Dlg::OnButtonRecEnd()

{

// TODO: Add your control notification handler code here

//设置接收数据结束标志

m_bRecEnd=TRUE;

}

UINT SendDataThread(LPVOID lpParam)

{

CTzg004Dlg *pDlg=(CTzg004Dlg *)lpParam;

CFile file;

if( !file.Open(pDlg->m_strFileName, CFile::modeRead) )

{

AfxMessageBox("打开文件出错!");

return 0;

}

CSocket sockTemp;

CString str,str1;

sockTemp.Create(pDlg->m_iDataPort1); //得到端口号

sockTemp.Listen(1);//只接受一个连接

CSocket sockSend;

//设置发送按钮禁止

pDlg->GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(FALSE);

sockTemp.Accept(sockSend);//注意,sockTemp已交了自己的指针地址到sockSend,故不用Close

//打开发送终止按钮

pDlg->GetDlgItem(IDC_BUTTON_SEND_END)->EnableWindow(TRUE);





int iBufSize = 1024 * 5;

int iSize = iBufSize;

LPBYTE pBuf = new BYTE[iBufSize];



DWORD dwTemp = 0;

BOOL bTest = sockSend.AsyncSelect(0);//由于CSocket实际是异步,将它变为同步(阻塞)方式。

sockSend.IOCtl( FIONBIO, &dwTemp);//用IOCtl要将AsyncSelect的第一个参数为0,参看MSDN



UINT uiLength = file.GetLength();

sockSend.Send(&uiLength, 4);//传送文件大小到接收方(Client端)



int iNumByte;

UINT uiTotal = 0;

yhy0611 2008-12-15
  • 打赏
  • 举报
回复
如果网络繁忙的情况下,以上代码会不会出现问题,写入太快,而对方却无法接收?
=============================================================


绝对会的,我现在正在经历这个问题,像1楼说用缓冲区可以解决,但我的问题太严重了,一个2K的包,可能要延迟十分钟,已经超出了程序控制的范围,正在建议用户把ADSL换成光纤
wangzhe1945 2008-12-15
  • 打赏
  • 举报
回复

while((number=filestream.Read(buffer,0,1024))!=0)
{
stream.Write(buffer,0,number);
stream.Flush();
Console.WriteLine(filestream.Position);
}

在循环中,如果网络问题,在stream.Write(buffer,0,number);
stream.Flush(); 中 ,写入会不会阻塞?
如果是,那么进度问题就能够控制了。
长沙三毛 2008-12-15
  • 打赏
  • 举报
回复
接收方应该缓冲文件数据:可扩展多线程异步Socket服务器框架EMTASS 2.0
内容概要:本文提出了一种基于改进扩散模型的高海拔地区新能源高波动出力场景生成方法,并提供了完整的Python代码实现。该方法针对高海拔地区风能、光伏等新能源出力波动剧烈、不确定性高的特点,通过优化扩散模型的结构与训练策略,有效捕捉历史数据的概率分布特征与时序相关性,从而生成高质量、多样化的出力场景。文中详细阐述了模型的数学推导、网络架构设计、损失函数优化及采样算法改进,并通过实验证明其在拟合精度、场景多样性与稳定性方面优于传统生成模型,为电力系统在高比例新能源接入下的规划、调度与风险评估提供了可靠的场景输入支持。; 适合人群:具备一定Python编程能力和机器学习基础,从事新能源发电预测、电力系统分析、智能优化、场景生成等方向研究的科研人员、高校研究生及工程技术人员。; 使用场景及目标:①用于高海拔地区风电、光伏出力的不确定性建模与多场景生成;②支撑含高渗透率新能源的电力系统随机优化调度、鲁棒决策与风险评估;③为相关学术研究、论文复现与算法改进提供可运行的技术方案与代码基础; 阅读建议:建议读者结合所提供的完整资源(代码、数据集、说明文档)进行实践操作,重点关注扩散模型的前向加噪与反向去噪过程的设计细节,以及如何将其适配于新能源时序数据的生成任务,通过参数调优与对比实验深入理解模型的生成机制与性能边界。
内容概要:本文围绕基于静态约束法的配电网电动汽车接入容量评估展开研究,提出了一种在新型电力系统背景下评估主动配电网对电动汽车承载能力的方法。研究通过构建数学模型,结合潮流计算与关键约束条件(如电压越限、线路过载等),量化分析配电网可承受的最大电动汽车充电负荷容量,旨在识别规模化电动汽车接入带来的潜在运行风险,并为电网规划与运行提供科学依据。文中配套提供了完整的Matlab代码实现,便于仿真验证与结果复现。此外,该研究与分布式光伏承载力评估、电动汽车可调能力分析等方向形成技术联动,展现了多主题协同的研究体系。; 适合人群:具备电力系统分析基础理论知识及Matlab编程能力的高校研究生、科研机构研究人员,以及从事新能源并网、智能配电网规划与运行等相关领域的工程技术人员。; 使用场景及目标:①用于学术研究中的模型复现与论文撰写支撑;②评估实际配电网中电动汽车大规模接入的可行性与安全边界,指导充电基础设施布局;③作为高校教学案例,帮助学生深入理解电网承载力评估的核心原理、建模方法与仿真技术; 阅读建议:建议结合文中提及的相关研究方向(如二阶锥规划、多面体聚合方法等)进行对比学习,充分利用所提供的Matlab代码与网盘资料开展仿真实验,重点关注约束条件的设定逻辑与潮流计算模块的实现细节,以深化对评估模型机理与工程应用价值的理解。
内容概要:本文围绕“考虑隐私保护的分布式联邦学习电力负荷预测研究”展开,提出了一种基于Python实现的联邦学习框架,旨在解决居民或行业电力负荷预测中用户电表数据隐私泄露的风险。该研究通过构建分布式机器学习模型,使各参与方在不共享原始数据的前提下协同训练全局模型,有效实现了数据“可用不可见”。文中详细阐述了联邦学习的整体架构设计、本地模型训练流程、参数加密传输与安全聚合机制,并结合差分隐私等技术进一步增强系统的隐私保护能力。同时,研究利用真实电力负荷数据集进行了实验验证,展示了方法在预测精度与隐私保障之间的良好平衡,并提供了完整的代码实例与复现指南,便于后续研究与应用拓展。; 适合人群:具备一定机器学习基础和电力系统背景知识,从事智慧能源、隐私计算或人工智能相关方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 实现跨区域、跨主体的电力负荷协同预测,打破数据孤岛;② 在确保用户用电数据隐私安全的前提下提升负荷预测准确性;③ 推动联邦学习在智能电网、需求响应、虚拟电厂等场景中的实际部署与应用。; 阅读建议:建议结合文中提供的Python代码与网盘资料进行动手实践,重点关注联邦学习的通信轮次设计、模型聚合算法(如FedAvg)的实现细节以及差分隐私噪声添加策略,深入理解其对模型性能与隐私强度的影响,为进一步优化与创新奠定基础。
VDA_Band_19.1_3rd edition_2026 English Inspection of Technical Cleanliness 内容概要:本文档为德国汽车工业协会(VDA)发布的第三版《技术清洁度检验:功能相关汽车部件的颗粒污染检测》(VDA 19.1),系统规范了汽车行业中零部件技术清洁度的检测方法与流程。文件涵盖从取样、提取、过滤到分析的全流程标准化操作,重点更新了干法提取(如 Stamp Test 和刷吸法)、小于50µm颗粒的检测、光学子系统和SEM/EDX标准分析方法,并引入统一材料分类体系以提升结果可比性。同时明确了“标准分析”与“自由检验”的区别,前者用于高兼容性检测,后者允许客户与供应商协商定制参数。文档还强化了对非可测组件的技术清洁保障、测量不确定度评估及方法验证的要求,并提供了多个实际案例支持应用落地。; 适合人群:适用于汽车制造业中从事质量控制、工艺开发、供应商管理及相关检测实验室的技术人员和管理人员,尤其适合具备一定质量管理或洁净度检测基础的专业人员。; 使用场景及目标:①用于制定和执行零部件清洁度检测标准;②指导 incoming/outgoing 检验及生产过程监控;③支持失效分析与质量改进项目;④作为企业内部审核和技术交流的依据; 阅读建议:建议结合VDA 19.2及其他相关标准配套使用,重点关注各章节中的起始参数设定、方法选择逻辑及附录中的检查表示例,在实际操作中同步开展方法验证与人员培训,确保检测结果的有效性和可追溯性。

111,130

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧