c++文件传输

2 篇文章 0 订阅
1 篇文章 0 订阅

序言

我这里给出的是一个简单的协议Demo,可以根据我注释里面的说明,自己丰富完善协议

关键代码

发送端

这里我放在了一个线程函数里面,加入了自己的协议结构,如果有兴趣可以自己提取出来使用这个模式。思考的大脑是你前行的灯,这里就没有摆出你直接Copy的接口。但是全部内容已在其中,不懂可以留言,我看到就回复。

typedef struct _FtProto
{
    BOOL  IsDone; 
    DWORD TotalSize;
    DWORD CurNo;
    BYTE  CurData[2048];
}FtProto,*PFtProto;

//发送文件的线程函数,lParameter 参数 是一个自定义结构体,里面包含了文件名等信息
DWORD frdTalkDlg::packFile(LPVOID lParameter)
{
	//转换成结构体指针
	PsendInfo msg = (PsendInfo)lParameter;
	//1. 打开文件
	CString fname;
	fname.Format(L"%s", msg->fileMsg.Bytes);
	//::MessageBox(NULL,fname, L"大小", MB_OK);
	ifstream infile(fname,ios::binary);
	if(!infile.is_open())
		::MessageBox(NULL, L"文件打开失败", L"大小", MB_OK);
	//2.获取大小
	infile.seekg(0, ios::end);
	int length = (int)infile.tellg();
	CString test;
	test.Format(L"%d", length);
	//测试大小是否获取成功, 问题? 为啥不能使用MessageBox()??
	//::MessageBox(NULL,test,L"大小",MB_OK);
	//3. 切片发送
	//3.1 指针设置回到文件开始的地方
	infile.seekg(0, ios::beg);
	//3.2 确定切片个数
	int totalNo = length % 1892 ? length / 1892 + 1 : length / 1892;
	test.Format(L"%d", totalNo);
	//::MessageBox(NULL, test, L"大小", MB_OK);
	int i = 0;
	//3.2 发送每一个切片
	while (i<totalNo)
	{
		//一个切片
		PsendInfo piece = new sendInfo;
		//切片信息
		piece->hWnd = msg->hWnd;
		piece->type = protoType::fileMsgTrp;
		//重新设置来源 和 目标
		memcpy(piece->fileMsg.fromID, msg->fileMsg.fromID, 64);
		memcpy(piece->fileMsg.toID, msg->fileMsg.toID, 64);

		//设置目标窗口的句柄
		piece->fileMsg.toWnd = msg->fileMsg.toWnd;

		//设置是否是最后一个的标志位
		piece->fileMsg.isdone = (i == totalNo - 1 )? 1 : 0;
		//设置切片的序号
		piece->fileMsg.No = i;
		//设置文件的总大小
		piece->fileMsg.totalLength = length;
		//拷贝当前切片的数据
		infile.read((char *)piece->fileMsg.Bytes, (i == totalNo - 1) ? length%1892:1892);
		
		//发送数据,通过Send函数发送
		::SendMessage(my->logDlg->GetSafeHwnd(), UM_SEND, NULL, (LPARAM)piece);
		i++;

	}
	::MessageBox(my->GetSafeHwnd(),L"文件传输完成!注意查收.",L"提醒",MB_OK);
	infile.close();

	return 0;
}

接收端

这里的代码是放在了MFC的一个消息处理函数里面,大家有兴趣的话提取出来放在你的代码里。大家要思考,思考才是进步的源泉。

//文件处理
afx_msg LRESULT frdTalkDlg::OnUmFlemsg(WPARAM wParam, LPARAM lParam)
{
	PsendInfo fileInfo = (PsendInfo)lParam;
	//初始化文件指针
	if (fileInfo->fileMsg.No == 0)
	{
		//如果以前传送过文件,则清理空间
		int totalNO = fileInfo->fileMsg.totalLength % 1892 
			? fileInfo->fileMsg.totalLength / 1892 + 1 : fileInfo->fileMsg.totalLength / 1892;
		fileP = new char[totalNO *1892];
		ZeroMemory(fileP, totalNO*1892);
	}
	//拷贝数据
	memcpy(fileP + 1892 * fileInfo->fileMsg.No, fileInfo->fileMsg.Bytes, 1892);
	//如果标志位已经完成则存储文件
	if (fileInfo->fileMsg.isdone == 1)
	{
		//以时间为名字命名
		SYSTEMTIME systime;
		GetSystemTime(&systime);
		CString fname;
		//以时间命名
		fname.Format(L"%d-%d-%d-%d-%d-%d", systime.wYear, systime.wMonth, systime.wDay,
			systime.wHour, systime.wMinute, systime.wSecond);
		//给文件名添加扩展名
		fname = fname + exName;
		//打开文件流
		ofstream outfile(fname, ios::binary);
		outfile.write(fileP, fileInfo->fileMsg.totalLength);
		outfile.close();
		MessageBox(L"文件接收完成:文件名- " + fname);

		delete[]fileP;
		fileP = nullptr;
	}
	return 0;
}


自定义文件协议

协议主体

传输大型文件的时候,肯定的一点是,你不可能通过一次数据包的发送 接收就实现文件的传输。所以,需要用到切片的思想给每一个切片数据一个编号,每个编号确定在文件的唯一位置。在接收方进行拼接组合最终保存。

typedef struct _FtProto
{
    BOOL  IsDone; //【可选】标志是否完成,可以本地借助编号和总大小计算是否完成但是有这个标着更直观
    DWORD TotalSize;//【可选】文件的总大小,可以自定义复杂的协议,在传输发起前协商好大小
    DWORD CurNo;//【必选】标志着当前数据包,是出于目标文件的那个位置
    BYTE  CurData[2048];//【必选】这个是当前数据包 -- 目标文件的一个切片数据,大小可以自定义
}FtProto,*PFtProto;

如果只是简单的传送文件,这个协议(结构体)完全已经能够满足。但是在大型项目中,想要形成完整的体系,稳定的系统,这是不够的。

完整的协议思想

这里的完整的协议,只是个人的经验总结,并不是标准规定,不能看了本文 反而局限 你的思想发散。

01 协议的协商

发送文件之前,需要先协商好文件的相关信息。

比如:
  • 文件的大小
  • 文件的类型
  • 文件的名称
  • 等等

02 协议数据包主体

即每个切片的数据包形式。

比如:
  • 切片的编号(便于在另一端组合文件的时候使用,以及检测是否有丢包)
  • 切片的数据

03 协议的完成

在我方数据包部分或全部发送完成后,另一端应该遵循一定的规则检测是否有丢包,如果有丢包应该请求再次发送。

比如:
  • 可以全部切片传输完毕后,最后确定是否有丢包。
  • 也可以每发送一部分,检测是否有丢包。
  • 如果有丢包,发起重发对应切片的请求。
  • 核对完毕,保存文件

以上三个主要步骤,都需要发送数据包。而每一种包又是一种格式(协议),如有需请自行设计相关字段。

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C文件传输协议是一种用于在计算机网络中进行文件传输的通信协议。它定义了文件的传输方式、数据格式和通信流程来保证文件可以有效地在网络传输和接收。 C文件传输协议采用了客户端-服务器模型,在网络中进行文件传输时,需要一个服务端和一个或多个客户端。服务端负责存储文件和提供服务,而客户端则负责请求文件和接收文件。 C文件传输协议的通信流程如下:首先,客户端发送连接请求给服务端;服务端确认连接请求,并建立连接;然后,客户端发送文件请求给服务端,包括文件名、起始位置和文件大小等信息;服务端接收文件请求,并根据请求将文件分成若干个数据包进行传输;客户端接收数据包,并根据数据包的顺序和内容进行重组;最后,客户端通知服务端文件传输完成,连接断开。 C文件传输协议的数据格式包括了文件名、文件大小、数据包序号和实际数据等信息。这些信息可以通过头部来标识和传输,以确保数据的准确传输和正确重组。 C文件传输协议主要通过TCP传输数据,因为TCP具有可靠性、有序性和流控制等特点,可以保证文件的完整传输。同时,C文件传输协议还可以配合文件压缩和加密等技术,提高传输效率和安全性。 总之,C文件传输协议是一种用于计算机网络文件传输的通信协议,通过定义数据格式和通信流程,保证文件能够有效地在网络传输和接收。它是现代计算机网络中重要的传输协议之一。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值