700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 一个简单的点对点文件传输程序

一个简单的点对点文件传输程序

时间:2020-10-09 00:05:03

相关推荐

一个简单的点对点文件传输程序

一个简单的点对点文件传输程序

黄定伍 402431143

在网络飞速发展的今天,信息的共享给我们带来了莫大的益处,而文件传输又是网络数据交换的主要形式,谈到文件传输大家可能会想到FTP文件传输协议,在这篇文件章中,我们并不汲及FTP.而是用windows socket来实现一个点对点文件传输.你可以把它想像成跟QQ里面的文件传输功能类似,只是我也不知道QQ里面所使用的是FTP或者是其它什么技术,但我是通过模拟它而实现本程序的.阅读本文章你需要具备一些MFC网络编程,和基本文件操作知识. 现在,来看看我是如何实现点对点文件传输功能的: 程序分为两个模块,一模块实现文件发送功能(服务器端),它需要创建一个socket并指定端口,然后监听,并等待客户端的连接,客户端连接上后用fopen二进制只读模式打开本地自己选择的一个文件,然后读取文件数据存放到一个数据结构中,通过socket发送给客户端;当然另一个模块的功能就是实现文件接收并写入磁盘了。它也需要创建一个socket,然后填写IP地址对服务器发送连接请求,服务器接收连接后发送一个数据结构过来,客户端通过数据结构内容得知文件名,文件大小,然后用fopen函数的二进制只写模式创建一个指定文件,然后通过数据接收写入,就可以实现点对点的文件传输了。 我是在VC6.0+WinXp sp1个人版上调试通过的。步骤如下: (1)创建一个支持window socket MFC基于对话框程序 (2)加入两个按钮控件,与一个文本框控件,并设置一个CString 变量m_strIP与文本框关连。 (3)在单击监听按钮事件加入下面代码: int nSend=0,nFileSize=0;

int cbSocketSend=0,nRead=0,dataID=1,dataID2=0;

int nSumPack=0;

CString Info;

SetWindowText("服务器");

GetDlgItem(IDC_CONNECT)->EnableWindow(false);

GetDlgItem(IDC_listen)->EnableWindow(false); //使连接按钮与监听按 钮无效

m_Server.Create(5177);

m_Server.Listen();

if(m_Server.Accept(m_Client))

{

MessageBox("有客户端连接上!","服务器:",MB_OK);

CFileDialog openFile(true);

if(openFile.DoModal()==IDOK)

{

FILE *pFile;

_DATA data;

pFile=fopen(openFile.GetPathName(),"rb"); //用二进制只读模式打开所选文件

fseek(pFile,0,SEEK_END); //文件指针移到文件尾 data.nFileSize=ftell(pFile); //得到文件大小

data.cbBuf=520;

data.dataID=-1;

data.IsEnd=38; //上面三个数据无意义

strcpy(data.szFileName,openFile.GetFileName());

fseek(pFile,0,SEEK_SET); //文件指针到文件头

m_Client.Send(&data,sizeof(data));

m_strMsg="等待客户端回应....";

UpdateData(false);

m_Client.Receive(&dataID,sizeof(dataID)); //接收一个整型变量

if(dataID!=0)

MessageBox("对方未准备好!!");

nSumPack=data.nFileSize/4096+1;

m_strMsg.Format("开始传输数据...估计数据包为%d个",nSumPack);

UpdateData(false);

Sleep(2000);

dataID=8;

m_Client.Send(&dataID,sizeof(dataID)); //通知开始传数据

nFileSize=data.nFileSize;

nSumPack=0;

while(nSend<nFileSize)

{

nSumPack++;

data.cbBuf=4*1024;

nRead=fread(data.szBuf,1,data.cbBuf,pFile);//读取4096字节数据

nSend+=nRead;//记录总共从文件读取了多少数据

data.cbBuf=nRead;

dataID++;

data.dataID=dataID;

if(nRead<4*1024)

data.IsEnd=TRUE;

cbSocketSend+=m_Client.Send(&data,sizeof(d ata));//发送数据

m_Client.Receive(&dataID2,sizeof(dataID2));//发送数据后确认对方是否正确收到

if(dataID2==dataID) //对方接收正确

{

if(nSumPack%10==0)

{

m_strMsg.Format("发送数据包ID=%d %d字节 成功-->文件总共 %d 字节已传送%d字节",dataID,data.cbBuf,nFileSize,nSend);

UpdateData(false);

Sleep(5);

}

}

else{

m_strMsg.Format("发送数据包ID=%d 共%d字节 失败!!!",dataID,data.cbBuf);

UpdateData(false);

Sleep(2000);

}

}

fclose(pFile);

Info.Format("发送完毕,总共发送 %d 字节! 读取文件长度: %d 实际文件长度为 %d字节",cbSocketSend,nSend,nFileSize);

MessageBox(Info,"提示!",MB_OK); m_Client.Close();

m_Server.Close();

GetDlgItem(IDC_listen)->EnableWindow(true);

}

}

(4)发连接按钮添加事件代码: _DATA data;

int nReceive=0,nFileSize=0,nWrite=0,dataID=0;

int nSumPack;

CString Info;

data.cbBuf=4*1024;

UpdateData();

if(m_strIP.IsEmpty())

{

MessageBox("服务器IP不能为空!");

return ;

} SetWindowText("客户端");

GetDlgItem(IDC_listen)->EnableWindow(false);

GetDlgItem(IDC_CONNECT)->EnableWindow(false);

m_Client.Create();

if(m_Client.Connect(m_strIP,5177))

{

MessageBox("已与服务器连上!!","客户端!",MB_OK);

m_Client.Receive(&data,sizeof(data));

Info.Format(" nFileSize=%d/n cbBuf=%d/n dataID=%d/n szFileName=%s/n szBuf=%s/n IsEnd=%d",

data.nFileSize,

data.cbBuf,

data.dataID,

data.szFileName,

data.szBuf);

MessageBox(Info); // 显示文件信息,其实没意义

nReceive=0;

nFileSize=data.nFileSize; //得到将要接收文件的大小

FILE *pFile;

nSumPack=nFileSize/4096+1;

dataID=0;

m_Client.Send(&dataID,sizeof(dataID));//回应服务器

m_Client.Receive(&dataID,sizeof(dataID));

if(dataID==8)

{

m_strMsg.Format("开始接收数据...共 %d 包 %d字节",nSumPack,nFileSize);

UpdateData(false);

Sleep(2000);

}

else

{

m_strMsg="未接收到数据可能出错...";

UpdateData(false);

Sleep(2000);

}

pFile=fopen(data.szFileName,"wb");//在当前目录创建指定文件

nSumPack=0;

while(nWrite<nFileSize)

{

nSumPack++;

nReceive+=m_Client.Receive(&data,sizeof(data));

if(data.cbBuf<0) //对方文件已读完

break;

nWrite+=data.cbBuf; //记录总共写入文件字节数

fwrite(data.szBuf,1,data.cbBuf,pFile);

fflush(pFile); //写入文件

m_Client.Send(&data.dataID,sizeof(int)); //回应服务器已接收到

if(nSumPack%10==0)

{

m_strMsg.Format("文件共 %d字节 已接收%d字节,正接收第 %d 个数据包 %字节 成功! ",nFileSize,nWrite,data.dataID,data.cbBuf);

UpdateData(false);

Sleep(5);

}

if(data.cbBuf<4096)//也是文件接收完毕

break;

}

fclose(pFile);

Info.Format("接收完毕,总共接收 %d 字节! 实际文件长度为 %d字节/n写入 %d字节",nReceive,nFileSize,nWrite);

MessageBox(Info,"提示!",MB_OK);

m_Client.Close();

GetDlgItem(IDC_CONNECT)->EnableWindow(true); } 下面是_DATA 结构的定义: typedef struct _tagDATA

{

int nFileSize; //记录文件大小以字节为单位

int cbBuf;

int dataID;

char szFileName[MAX_PATH]; //记录文件名

char szBuf[4*1024]; //读取文件的数据缓冲区

BOOL IsEnd;

}_DATA; 本程序实际是将服务器端模块与客户端模块集成在一个程序里面,运行后单击监听,则这个程序实例就是服务器端,运行后如果单击的是连接那么就是客户端。程序只能单向传输,并且客户端是无条件接收并存放到客户端程序当前目录,有兴趣的可以将其改进并用CFile实现。 转载请联系我:402431143

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。