点对点多线程断点续传的实现

VC++环境下点对点多线程断点续传实现 点对点(Peer-to-Peer,简称P2P)网络架构是一种去中心化的网络模型,在该架构中,网络的每个节点既是客户端又是服务器,可以直接与其他节点通信,共享资源和服务。P2P网络因其高度的可扩展性、鲁棒性和负载均衡能力,在分布式计算、文件共享、区块链等多个领域得到了广泛应用。在VC++中,文件IO操作主要是通过标准C++库和Windows API来完成的。C++标准库提供了一套较为简单的文件IO接口,例如<fstream>库中的ifstream和ofstream等。 阅读详情

在如今的网络应用中,文件的传送是重要的功能之一,也是共享的基础。一些重要的协议像HTTP,FTP等都支持文件的传送。尤其是FTP,它的全称就是“文件传送协议”,当初的工程师设计这一协议就是为了解决网络间的文件传送问题,而且以其稳定,高速,简单而一直保持着很大的生命力。作为一个程序员,使用这些现有的协议传送文件相当简单,不过,它们只适用于服务器模式中。这样,当我们想在点与点之间传送文件就不适用了或相当麻烦,有一种大刀小用的意味。笔者一直想寻求一种简单有效,且具备多线程断点续传的方法来实现点与点之间的文件传送问题,经过大量的翻阅资料与测试,终于实现了,现把它共享出来,与大家分享。
我写了一个以此为基础的实用程序(网络传圣,包含源代码),可用了基于TCP/IP的电脑上,供大家学习。


(本文源代码运行效果图)


实现方法(VC++,基于TCP/IP协议)如下:
仍釆用服务器与客户模式,需分别对其设计与编程。
服务器端较简单,主要就是加入待传文件,监听客户,和传送文件。而那些断点续传的功能,以及文件的管理都放在客户端上。

一、服务器端

首先介绍服务器端:
最开始我们要定义一个简单的协议,也就是定义一个服务器端与客户端听得懂的语言。而为了把问题简化,我就让服务器只要听懂两句话,一就是客户说“我要读文件信息”,二就是“我准备好了,可以传文件了”。
由于要实现多线程,必须把功能独立出来,且包装成线程,首先建一个监听线程,主要负责接入客户,并启动另一个客户线程。我用VC++实现如下:

DWORD WINAPI listenthread(LPVOID lpparam)
{	

    //由主函数传来的套接字
  SOCKET  pthis=(SOCKET)lpparam;
    //开始监听
	int rc=listen(pthis,30);
    //如果错就显示信息
    if(rc<0){
	  CString aaa;
	  aaa="listen错误/n";
      AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
	  aaa.ReleaseBuffer();
	  return 0;
	}
    //进入循环,并接收到来的套接字
	while(1){
    //新建一个套接字,用于客户端
	SOCKET s1;
	s1=accept(pthis,NULL,NULL);
	
   //给主函数发有人联入消息
    CString aa;
    aa="一人联入!/n";
    AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aa.GetBuffer(0),1);
	aa.ReleaseBuffer();
	DWORD dwthread;
    //建立用户线程
	::CreateThread(NULL,0,clientthread,(LPVOID)s1,0,&dwthread);	
	}
	return 0;
}
接着我们来看用户线程:
先看文件消息类定义:
struct fileinfo
{
	int fileno;//文件号
	int type;//客户端想说什么(前面那两句话,用1,2表示)
	long len;//文件长度
	int seek;//文件开始位置,用于多线程

	char name[100];//文件名
};
用户线程函数:
DWORD WINAPI clientthread(LPVOID lpparam)
{
	//文件消息
	fileinfo* fiinfo;
	//接收缓存
	char* m_buf;
	m_buf=new char[100];
	//监听函数传来的用户套接字
	SOCKET  pthis=(SOCKET)lpparam;
	//读传来的信息
	int aa=readn(pthis,m_buf,100);
	//如果有错就返回
	if(aa<0){
		closesocket (pthis);
		return -1;
	}
	//把传来的信息转为定义的文件信息
	fiinfo=(fileinfo*)m_buf;
	CString aaa;
	//检验客户想说什么
	switch(fiinfo->type)
	{
	//我要读文件信息
	case 0:
	//读文件
	aa=sendn(pthis,(char*)zmfile,1080);
	//有错
	if(aa<0){	
		closesocket (pthis);
		return -1;
	}
	//发消息给主函数
	aaa="收到LIST命令/n";
    	AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
	break;
	//我准备好了,可以传文件了

	case 2:
	//发文件消息给主函数
	aaa.Format("%s  文件被请求!%s/n",zmfile[fiinfo->fileno].name,nameph[fiinfo->fileno]);
	AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
	//读文件,并传送
	readfile(pthis,fiinfo->seek,fiinfo->len,fiinfo->fileno);
	//听不懂你说什么

	default:
	aaa="接收协议错误!/n";
    	AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
	break;
}

	return 0;
}
读文件函数
void readfile(SOCKET  so,int seek,int len,int fino)
{
	//文件名
	CString myname;
	myname.Format("%s",nameph[fino]);
	CFile myFile;
	//打开文件
	myFile.Open(myname, CFile::modeRead | CFile::typeBinary|CFile::shareDenyNone); 
	//传到指定位置 
	myFile.Seek(seek,CFile::begin);
	char m_buf[SIZE];
	int len2;
	int len1;
	len1=len;
	//开始接收,直到发完整个文件
	while(len1>0){
		len2=len>SIZE?SIZE:len;
		myFile.Read(m_buf, len2);
		int aa=sendn(so,m_buf,len2);
	if(aa<0){	
		closesocket (so);
		break;
	}
	len1=len1-aa;
	len=len-aa;
	}
	myFile.Close();
}

服务器端最要的功能各技术就是这些,下面介绍客户端。

二、客户端

客户端最重要,也最复杂,它负责线程的管理,进度的记录等工作。

大概流程如下:
先连接服务器,接着发送命令1(给我文件信息),其中包括文件长度,名字等,然后根据长度决定分几个线程下载,并初使化下载进程,接着发送命令2(可以给我传文件了),并记录文件进程。最后,收尾。
这其中有一个十分重要的类,就是cdownload类,定义如下:

class cdownload  
{
public:
	void createthread();//开线程
	DWORD finish1();//完成线程
	int sendlist();//发命令1
	downinfo doinfo;//文件信息(与服务器定义一样)
	int startask(int n);开始传文件n
	long m_index;
	BOOL good[BLACK];
	int  filerange[100];
	CString fname;
	CString fnametwo;
	UINT threadfunc(long index);//下载进程

	int sendrequest(int n);//发文件信息
	cdownload(int thno1);
	virtual ~cdownload();
};
下面先介绍sendrequest(int n),在开始前,向服务器发获得文件消息命令,以便让客户端知道有哪些文件可传
int cdownload::sendrequest(int n)
{
	//建套接字
	sockaddr_in local;
	SOCKET m_socket;

	int rc=0;
	//初使化服务器地址
	local.sin_family=AF_INET;
	local.sin_port=htons(1028);
	local.sin_addr.S_un.S_addr=inet_addr(ip);
	m_socket=socket(AF_INET,SOCK_STREAM,0);

	
	int ret;
	//联接服务器
	ret=connect(m_socket,(LPSOCKADDR)&local,sizeof(local));
	//有错的话
	if(ret<0){
		AfxMessageBox("联接错误");
	closesocket(m_socket);
	return -1;
	}
	//初使化命令
	fileinfo fileinfo1;
	fileinfo1.len=n;
	fileinfo1.seek=50;
	fileinfo1.type=1;
	//发送命令
	int aa=sendn(m_socket,(char*)&fileinfo1,100);
	if(aa<0){
		closesocket(m_socket);
		return -1;
	}
	//接收服务器传来的信息
	 aa=readn(m_socket,(char*)&fileinfo1,100);
	if(aa<0){
		closesocket(m_socket);
		return -1;
	}
	//关闭
	shutdown(m_socket,2);
	closesocket(m_socket);

	return 1;
}
有了文件消息后我们就可以下载文件了。在主函数中,用法如下:
//下载第clno个文件,并为它建一个新cdownload类
down[clno]=new cdownload(clno);
//开始下载,并初使化
type=down[clno]->startask(clno);
//建立各线程
createthread(clno);
下面介绍开始方法:
//开始方法
int cdownload::startask(int n)
{
	//读入文件长度
	doinfo.filelen=zmfile[n].length;
	//读入名字
	fname=zmfile[n].name;
	CString tmep;
	//初使化文件名
	tmep.Format("//temp//%s",fname);

	//给主函数发消息
	CString aaa;
	aaa="正在读取 "+fname+" 信息,马上开始下载。。。/n";
	AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
	aaa.ReleaseBuffer();
	//如果文件长度小于0就返回
	if(doinfo.filelen<=0) return -1;
	//建一个以.down结尾的文件记录文件信息
	CString m_temp;
	m_temp=fname+".down";
	
	doinfo.name=m_temp;
	FILE* fp=NULL;
	CFile myfile;
	//如果是第一次下载文件,初使化各记录文件

	if((fp=fopen(m_temp,"r"))==NULL){
	filerange[0]=0;
	//文件分块
	for(int i=0;i<BLACK;i++)
	{
		if(i>0)
			filerange[i*2]=i*(doinfo.filelen/BLACK+1);
		filerange[i*2+1]=doinfo.filelen/BLACK+1;
	}
	filerange[BLACK*2-1]=doinfo.filelen-filerange[BLACK*2-2];

	myfile.Open(m_temp,CFile::modeCreate|CFile::modeWrite | CFile::typeBinary);

	//写入文件长度
	myfile.Write(&doinfo.filelen,sizeof(int));
	myfile.Close();
 
	CString temp;
	for(int ii=0;ii<BLACK;ii++){
	//初使化各进程记录文件信息(以.downN结尾)

	temp.Format(".down%d",ii);
	m_temp=fname+temp;
	myfile.Open(m_temp,CFile::modeCreate|CFile::modeWrite | CFile::typeBinary);
	//写入各进程文件信息
	myfile.Write(&filerange[ii*2],sizeof(int));
	myfile.Write(&filerange[ii*2+1],sizeof(int));
	myfile.Close();
	}

	((CMainFrame*)::AfxGetMainWnd())->m_work.m_ListCtrl->AddItemtwo(n,2,0,0,0,doinfo.threadno);
	}
	else{
	//如果文件已存在,说明是续传,读上次信息
	CString temp;
 
	m_temp=fname+".down0";
	if((fp=fopen(m_temp,"r"))==NULL)
		return 1;
	else fclose(fp);

	int bb;
	bb=0;
	//读各进程记录的信息
	for(int ii=0;ii<BLACK;ii++)
	{
		temp.Format(".down%d",ii);
		m_temp=fname+temp;
 
		myfile.Open(m_temp,CFile::modeRead | CFile::typeBinary);
		myfile.Read(&filerange[ii*2],sizeof(int));
		myfile.Read(&filerange[ii*2+1],sizeof(int));
		myfile.Close();

		bb = bb+filerange[ii*2+1];
		CString temp;
	}
	if(bb==0) return 1;
	doinfo.totle=doinfo.filelen-bb;
 
	((CMainFrame*)::AfxGetMainWnd())->m_work.m_ListCtrl->AddItemtwo(n,2,doinfo.totle,1,0,doinfo.threadno);

	}

 	//建立下载结束进程timethread,以管现各进程结束时间。
	DWORD dwthread;
	::CreateThread(NULL,0,timethread,(LPVOID)this,0,&dwthread);

	return 0;
}
下面介绍建立各进程函数,很简单:
void CMainFrame::createthread(int threadno)
{
	DWORD dwthread;
	//建立BLACK个进程
	for(int i=0;i<BLACK;i++)
	{
		m_thread[threadno][i]=	::CreateThread(NULL,0,downthread,(LPVOID)down[threadno],0,&dwthread);
	}
}
downthread进程函数
DWORD WINAPI downthread(LPVOID lpparam)
{
	cdownload* pthis=(cdownload*)lpparam;
	//进程引索+1
	InterlockedIncrement(&pthis->m_index);
	//执行下载进程
	pthis->threadfunc(pthis->m_index-1);
	return 1;
}
下面介绍下载进程函数,最最核心的东西了
UINT cdownload::threadfunc(long index)
{
	//初使化联接
	sockaddr_in local;
	SOCKET m_socket;

	int rc=0;
 
	local.sin_family=AF_INET;
	local.sin_port=htons(1028);
	local.sin_addr.S_un.S_addr=inet_addr(ip);
	m_socket=socket(AF_INET,SOCK_STREAM,0);

	int ret;
	//读入缓存
	char* m_buf=new char[SIZE];
	int re,len2;
	fileinfo fileinfo1;
	//联接
	ret=connect(m_socket,(LPSOCKADDR)&local,sizeof(local));
	//读入各进程的下载信息
	fileinfo1.len=filerange[index*2+1];
	fileinfo1.seek=filerange[index*2];
	fileinfo1.type=2;
	fileinfo1.fileno=doinfo.threadno;
 
	re=fileinfo1.len;
 
	//打开文件 
	CFile destFile;
	FILE* fp=NULL;
	//是第一次传的话
	if((fp=fopen(fname,"r"))==NULL)
		destFile.Open(fname, CFile::modeCreate|CFile::modeWrite | CFile::typeBinary|CFile::shareDenyNone);
	else
		//如果文件存在,是续传
		destFile.Open(fname,CFile::modeWrite | CFile::typeBinary|CFile::shareDenyNone);
	//文件指针移到指定位置
	destFile.Seek(filerange[index*2],CFile::begin);
	//发消息给服务器,可以传文件了
	sendn(m_socket,(char*)&fileinfo1,100);

	CFile myfile;
	CString temp;
	temp.Format(".down%d",index);
	m_temp=fname+temp;

 	//当各段长度还不为0时
	while(re>0){
		len2=re>SIZE?SIZE:re;
 
		//读各段内容
		int len1=readn(m_socket,m_buf,len2);
		//有错的话
		if(len1<0){
			closesocket(m_socket);
			break;
		}
 
	//写入文件
	destFile.Write(m_buf, len1);	

	//更改记录进度信息

	filerange[index*2+1]-=len1;
	filerange[index*2]+=len1;
	//移动记录文件指针到头
	myfile.Seek(0,CFile::begin);
	//写入记录进度
	myfile.Write(&filerange[index*2],sizeof(int));
	myfile.Write(&filerange[index*2+1],sizeof(int));

	//减去这次读的长度
	re=re-len1;

	//加文件长度
	doinfo.totle=doinfo.totle+len1;
	};
	
	//这块下载完成,收尾
 
	myfile.Close();
	destFile.Close();
	delete [] m_buf;
	shutdown(m_socket,2);
 
 
	if(re<=0) good[index]=TRUE;
	return 1;
}

到这客户端的主要模块和机制已基本介绍完。希望好好体会一下这种多线程断点续传的方法。


 
TCP文件传输系统(Version 1.6 多线程,断点续传,支持大文件传输) 采用Visual C++ 6.0开发的一个TCP文件传输系统,采用多线程的传输方式,支持断点续传,利用配置文件设置基本的初始化信息。 文件包括源代码和安装包,源代码里包括自定义的文件传输通信协议。 程序采用分层的设计方案,将底层的配置文件和文件操作封装成基本模型组件,并定义了文件传输模型,提供视图和底层模型进行交互的外观;视图层分离为视图和控制两块,视图信息的更新由控制层进行控制。 新版本利用内存文件映射的技术重写了文件模型,使得程序支持大文件的传输(最大16EB),提高了文件操作效率;此外,改善了视图的显示方式,更加方便了传输进度信息的查看。 立即下载

相关推荐

TCP协议的断点续传.rar

TCP协议的断点续传.rar

点对点(P2P)多线程断点续传的实现

点对点(P2P)多线程断点续传的实现作者: 赵明 | 日期: 2004-06-21 | 已阅: 19063次P2P中国下载源代码:upload/2004_06/04062118573143.zip <!--google_ad_client = "pub-7197438303445134";google_ad_width = 300;google_ad_height = 250;

beyondpeijie的专栏 1848

Vc++ 点对点文件传输程序源文件

内容索引:VC/C++源码,网络相关,文件传输  Vc++ 点对点文件传输源程序,相对简单的那种,需要在客户端指定IP地址,在服务端浏览所要发送的文件,点确认即可。程序面向VC++初学者,简洁明了,作为初级网络编程实例值得参阅。

C++ 关于断点续传的方法,使用CURL技术

STEP1 CURL *curlhandle = NULL; // curl_global_init(CURL_GLOBAL_ALL); curlhandle = curl_easy_init(); bool flag = download(curlhandle,myvar->url.c_str(),myvar->path.c_str(), myvar->proxy_addr

MAC 应用开发 3255

PADS安装教程(超详细)

声明:个人实践 一、工具准备 pads9.5完整破解版百度网盘提取码【wjx9】 链接:https://pan.baidu.com/s/1pIP6BJO435ssmF7Hjwyz8A 提取码:wjx9 安装环境:win10 64位 二、开始解压安装 关闭杀毒,exe以管理员身份运行 点击【skip】,不然又得licese 点击【agree】 点击【modify】 设置安装的工具、路径及工程路径 设置完成后,开始【install】 在之后注册。 将Crack复制到PADS安装目录

qq_42057393的博客 5万+

LD分析实战:基于Plink和R的连锁不平衡计算与可视化全流程

本文详细介绍了基于Plink和R的连锁不平衡(LD)分析全流程,包括基因型数据预处理、LD计算参数设置及结果可视化技巧。通过实战案例解析PLINK文件格式转换、r²值计算关键参数,并展示如何使用ggplot2绘制高质量LD热图,帮助研究人员高效完成基因组关联分析。

weixin_29074295的博客 319

蓝牙协议分析_BLE地址类型

SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。SYD8801片上集成了Balun无需阻抗匹配网络、高效率DCDC降压转换器,适合用于可穿戴、物联网设备等。具体可咨询:http://www.sydtek.com/ 1. 前言 也许关注BLE的同学都注意到了,BLE设备...

挖到尽头 1万+

Quartus ||———基于Verilog HDL的数字秒表设计实验

Quartus ||———基于Verilog HDL的数字秒表设计实验一、实验目的二、实验步骤(一)新建工程(二)添加设计文件(三)综合分析与功能仿真1、综合分析2、功能仿真 一、实验目的 用Verilog HDL设计一个数字跑表,所需引脚和功能如下: 二、实验步骤 (一)新建工程 在创建好工程名称后,选定芯片类型 (二)添加设计文件 新建Verilog文件,键入代码如下 module n_clk_top( input clk, input rese

TBMmagic的博客 5525

如何点对点实现多线程断点续传

如何点对点实现多线程断点续传 <!--google_ad_client = "pub-9346728666813782";google_alternate_color = "FFFFFF";google_ad_width = 250;google_ad_height = 250;google_ad_format = "250x250_as";google_ad_type

c0ffee1982的专栏 673

基于STM32F4通用定时器实现Livox激光雷达PPS硬件同步的工程实践

本文详细介绍了基于STM32F4通用定时器实现Livox激光雷达PPS硬件同步的工程实践。通过分析PPS信号的时序要求,对比不同定时器的特性,并提供完整的代码实现与调试技巧,帮助开发者解决多传感器数据融合中的时间同步问题。实测表明,该方案在车载环境中稳定运行超过2000小时。

weixin_30540691的博客 324

基于 MATLAB 的 FastICA 算法实现语音信号盲分离

FastICA 算法通过最大化信号的非高斯性,找到独立成分,从而实现信号的分离。这些混合的信号被称为盲源信号,我们希望通过分析混合信号,将它们分离出来以便进行进一步的处理和分析。FastICA 是一种常用的盲源信号分离算法,它基于统计学原理,通过寻找独立成分来实现信号的分离。FastICA(独立成分分析)是一种常用的盲源信号分离算法,在语音和图像处理领域都有广泛的应用。本文将介绍如何使用 MATLAB 实现 FastICA 算法来实现语音信号的盲分离,并提供相应的源代码。FastICA 算法原理。

学习使你进步。 2024

一种点对点文件断点续传的多线程实现方法

分类: IMS 2009-08-28 10:05 94人阅读 评论(0) 收藏 举报 1 概述     文件断点续传就是在主机与主机间传输文件时,可以将文件分多次传输,与非断点续传不同的是,每次传输不必传输整个文件。断点续传是大型文件数据传输的核心。本文将以多线程技术和Socket技术为依托,介绍大型文件断点续传的实现方法。     2 基本实现思想     多线程断

wxl1986622的专栏 859

SAP物料主数据归档详解(物理删除)

顾问们的回答肯定的统一的不能,只能打上删除标记。物料设置好需要删除的物料号这里我们需要删除的物料是AG88,其中,若不选“考虑无删除标记的物料”,需要将需要归档的物料MM06打删除标记。平时在操作系统过程中经常会不小心创建出很多无用的物料主数据,但是系统只能通过MM06打上删除标记,但是物料最终在系统中还是可以查询到的。6、执行已设置变式的归档程序,执行完毕,点下图中的“Job”,每次执行完归档程序会产生两条作业。然后设置好开始的参数和假脱机的参数,三个都是绿灯就可以执行归档的操作,物理上删除物料主数据。

我小时候很黑的博客 5523

[VC++]点对点(P2P)多线程断点续传的实现(TCP/IP)

 在如今的网络应用中,文件的传送是重要的功能之一,也是共享的基础。一些重要的协议像HTTP,FTP等都支持文件的传送。尤其是FTP,它的全称就是“文件传送协议”,当 初的工程师设计这一协议就是为了解决网络间的文件传送问题,而且以其稳定,高速,简单而一直保持着很大的生命力。作为一个程序员,使用这些现有的协议传送文件相当简单,不过,它们只适用于服务器模式中。这样,当我们想在点与点之间传送文件就

Daniel 2189

【DRAM存储器五十一】LPDDR5介绍--DFE与Pre-Emphasis

简述LPDDR5的DFE和预加重应用设置

highman110的博客 705

华为服务器BMC方式安装系统-官方文档解读

华为服务器BMC方式安装系统 安装完成之后我们有两种方式去安装系统, > 一、服务器连接显示屏、键盘、鼠标和启动盘去启动服务器安装系统(弊端:需要制作单独启动盘并且需要硬件资源) > 二、使用BMC方式安装系统,也就是说使用网线连接我们的笔记本和服务器的BMC口或者mgt口去进行安装。

王明的博客 4579

点对点(P2P)多线程断点续传的实现(转贴)

在如今的网络应用中,文件的传送是重要的功能之一,也是共享的基础。一些重要的协议像HTTP,FTP等都支持文件的传送。尤其是FTP,它的全称就是 “文件传送协议”,当 初的工程师设计这一协议就是为了解决网络间的文件传送问题,而且以其稳定,高速,简单而一直保持着很大的生命力。作为一个程序员,使用这些现有的协议传送 文件相当简单,不过,它们只适用于服务器模式中。这样,当我们想在点与点之间传...

diefei3662的博客 294

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

[VC++]点对点(P2P)多线程断点续传的实现

在如今的网络应用中,文件的传送是重要的功能之一,也是共享的基础。一些重要的协议像HTTP,FTP等都支持文件的传送。尤其是FTP,它的全称就是“文件传送协议”,当 初的工程师设计这一协议就是为了解决网络间的文件传送问题,而且以其稳定,高速,简单而一直保持着很大的生命力。作为一个程序员,使用这些现有的协议传送文件相当简单,不过,它们只适用于服务器模式中。这样,当我们想在点与点之间传送文件就不适用了或

张彤的专栏 2664

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

上一篇: ftp协议实现多线程断点续传
下一篇: #define和typedef的区别
JamesXing
博客等级 码龄20年 30粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值