版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、使用TCP协议实现文件传输2013-01-18 10:35:43 我来说两句 作者:hanchaoqi收藏 我要投稿 使用TCP协议实现文件传输。程序会分为服务器端和客户端,首先运行服务器端,监听来自客户端的连接,客户端运行后会通过程序内的服务器端IP地址,向服 务器发送连接请求。双方建立请求之后,客户端将所需文件的文件名和绝对路径传输给服务器,如果服务器找到此文件,则将此文件传输给客户端,然后断开连接。 具体算法描述如下:【1】服务器端:1、初始化socket服务2、监听连接请求并做相应的处理2.1创建监听套接字2.2监听套接口2.3接受套接字的连接2.4接收客户端传来的数据case 文件绝
2、对路径:按照路径找到文件,并打开。提取本地文件名,发回给客户端发送文件总长度给客户端case 已准备接收文件完毕if 发送缓冲区为空读取文件,写入缓冲区将文件流分成大小相同的组(最后一组可能会小一点),顺次发送给客户端将缓冲区清空case 文件成功传送打印消息,退出case 文件已存在打印消息,退出2.5关闭同客户端的连接3、释放socket服务【2】客户端:1、初始化socket,winsock服务2、连接服务器,进行数据的传输2.1初始化,创建套接字2.2通过IP地址,向服务器发送连接请求,建立连接2.3主动发送所求文件绝对路径2.4接受服务器端数据并做相应处理case 打开文件错误:重新
3、发送文件绝对路径至服务器,请求重发case 文件长度:打印消息case 文件名:if 文件已经存在发送“文件已经存在”else分配缓冲区,并向服务器发送“Ready”消息case 文件流:为已接收文件名创建文件打开文件,将文件流数据写入文件,直至接收所有分组数据发送“成功接收“消息3、关闭套接字释放服务源程序:【1】服务器端:头文件:cpp /*server.h*/ #pragma comment(lib, WS2_32) #include #include #include #include #ifndef COMMONDEF_H #define COMMONDEF_H #define MA
4、X_PACKET_SIZE 10240 / 数据包的最大长度,单位是sizeof(char) #define MAXFILEDIRLENGTH 256 / 存放文件路径的最大长度 #define PORT 4096 / 端口号 /#define SERVER_IP 127.0.0.1 / server端的IP地址 / 各种消息的宏定义 #define INVALID_MSG -1 / 无效的消息标识 #define MSG_FILENAME 1 / 文件的名称 #define MSG_FILELENGTH 2 / 传送文件的长度 #define MSG_CLIENT_READY 3 / 客户端
5、准备接收文件 #define MSG_FILE 4 / 传送文件 #define MSG_SENDFILESUCCESS 5 / 传送文件成功 #define MSG_OPENFILE_ERROR 10 / 打开文件失败,可能是文件路径错误找不到文件等原因 #define MSG_FILEALREADYEXIT_ERROR 11 / 要保存的文件已经存在了 class CCSDef public: #pragma pack(1) / 使结构体的数据按照1字节来对齐,省空间 / 消息头 struct TMSG_HEADER char cMsgID; / 消息标识 TMSG_HEADER(char
6、 MsgID = INVALID_MSG) : cMsgID(MsgID) ; / 请求传送的文件名 / 客户端传给服务器端的是全路径名称 / 服务器传回给客户端的是文件名 struct TMSG_FILENAME : public TMSG_HEADER char szFileName256; / 保存文件名的字符数组 TMSG_FILENAME() : TMSG_HEADER(MSG_FILENAME) ; / 传送文件长度 struct TMSG_FILELENGTH : public TMSG_HEADER long lLength; TMSG_FILELENGTH(long leng
7、th) : TMSG_HEADER(MSG_FILELENGTH), lLength(length) ; / Client端已经准备好了,要求Server端开始传送文件 struct TMSG_CLIENT_READY : public TMSG_HEADER TMSG_CLIENT_READY() : TMSG_HEADER(MSG_CLIENT_READY) ; / 传送文件 struct TMSG_FILE : public TMSG_HEADER union / 采用union保证了数据包的大小不大于MAX_PACKET_SIZE * sizeof(char) char szBuffM
8、AX_PACKET_SIZE; struct int nStart; int nSize; char szBuffMAX_PACKET_SIZE - 2 * sizeof(int); tFile; ; TMSG_FILE() : TMSG_HEADER(MSG_FILE) ; / 传送文件成功 struct TMSG_SENDFILESUCCESS : public TMSG_HEADER TMSG_SENDFILESUCCESS() : TMSG_HEADER(MSG_SENDFILESUCCESS) ; / 传送出错信息,包括: / MSG_OPENFILE_ERROR:打开文件失败 /
9、MSG_FILEALREADYEXIT_ERROR:要保存的文件已经存在了 struct TMSG_ERROR_MSG : public TMSG_HEADER TMSG_ERROR_MSG(char cErrorMsg) : TMSG_HEADER(cErrorMsg) ; #pragma pack() ; #endif cpp文件:cpp /*Server.cpp*/ #includeServer.h char g_szNewFileNameMAXFILEDIRLENGTH; char g_szBuffMAX_PACKET_SIZE + 1; long g_lLength; char* g
10、_pBuff = NULL; /初始化socket库 bool InitSocket(); /关闭socket库 bool CloseSocket(); /解析消息并进行相应的处理 bool ProcessMsg(SOCKET sClient); /监听Client消息 void ListenToClient(); /打开文件 bool OpenFile(CCSDef:TMSG_HEADER* pMagHeader,SOCKET sClient); /传送文件 bool SendFile(SOCKET sClient); /读取文件进缓冲区 bool ReadFile(SOCKET sClie
11、nt); int main() while(1) InitSocket(); ListenToClient(); CloseSocket(); system(del E:test1.A_exp); /system(pause); return 0; /初始化socket库 bool InitSocket() WSADATA wsaData; WORD socketVersion=MAKEWORD(2,2); if(:WSAStartup(socketVersion,&wsaData)!=0) /初始化WinSock服务 printf(Init socket dll errorn); retur
12、n false; return true; /关闭socket库 bool CloseSocket() /释放winsock库 :WSACleanup(); if(g_pBuff != NULL) delete g_pBuff; g_pBuff = NULL; return true; /解析消息并进行相应的处理 bool ProcessMsg(SOCKET sClient) /从套接口中接收数据,返回copy的字节数 int nRecv = :recv(sClient,g_szBuff,MAX_PACKET_SIZE+1,0); if(nRecv0) g_szBuffnRecv=0; /解析
13、命令 CCSDef:TMSG_HEADER* pMsgHeader=(CCSDef:TMSG_HEADER*)g_szBuff; switch(pMsgHeader-cMsgID) case MSG_FILENAME:/文件名 OpenFile(pMsgHeader,sClient); break; case MSG_CLIENT_READY:/客户端已准备完毕,开始传送文件 SendFile(sClient); break; case MSG_SENDFILESUCCESS:/传送文件成功 printf(Send File Success!n); return false; break; c
14、ase MSG_FILEALREADYEXIT_ERROR:/要保存的文件已经存在 printf(The file ready to send already exit!n); return false; break; return true; /监听Client消息 void ListenToClient() /创建套接字 SOCKET sListen = :socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sListen = SOCKET_ERROR) printf(Init Socket Error!n); return; /绑定socket s
15、ockaddr_in sin; sin.sin_family=AF_INET; sin.sin_port=htons(PORT); sin.sin_addr.S_un.S_addr=INADDR_ANY; if (:bind(sListen, (LPSOCKADDR)&sin, sizeof(sockaddr_in) = SOCKET_ERROR) printf(Bind Error!n); return; / 设置socket进入监听状态 if(:listen(sListen,10)=SOCKET_ERROR) printf(Listen Error!n); return; printf(L
16、istening To Client.n); /循环接收client端的连接请求 sockaddr_in ClientAddr; int nAddrLen = sizeof(sockaddr_in); SOCKET sClient; /取队列最前端客户连接请求,创建套接字连接通道 while(sClient=:accept(sListen,(sockaddr*)&ClientAddr,&nAddrLen)=INVALID_SOCKET) /解析消息并进行相应的处理 /int count=10;/作为定时当程序执行10s未完成时直接退出 /while(ProcessMsg(sClient)=tr
17、ue&count0) / / Sleep(1000); / count-; / while(ProcessMsg(sClient)=true) Sleep(1000); /关闭同客户端的连接 :closesocket(sClient); :closesocket(sListen); /打开文件 bool OpenFile(CCSDef:TMSG_HEADER* pMsgHeader,SOCKET sClient) CCSDef:TMSG_FILENAME* pRequstFileNameMsg=(CCSDef:TMSG_FILENAME*)pMsgHeader; /对文件名进行处理 char
18、*p1,*p2; for(p1=pRequstFileNameMsg-szFileName,p2=g_szNewFileName;*p1!=0;p1+,p2+) if(*p1!=n) *p2=*p1; if(*p2=)/将转换为 *(+p2)=; *p2=0; ReadFile(sClient); return true; /传送文件 bool SendFile(SOCKET sClient) if (NULL = g_pBuff) /如果缓冲区为空 ReadFile(sClient); int nPacketBufferSize = MAX_PACKET_SIZE - 2 * sizeof(
19、int); / 每个数据包存放文件的buffer大小 / 如果文件的长度大于每个数据包所能传送的buffer长度那么就分块传送 for (int i = 0; i g_lLength) /文件块已经是最后一块 tMsgFile.tFile.nSize = g_lLength - i; else tMsgFile.tFile.nSize = nPacketBufferSize; memcpy(tMsgFile.tFile.szBuff, g_pBuff + tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);/copy到缓冲区 :send(sClient,
20、(char*)(&tMsgFile), sizeof(CCSDef:TMSG_FILE), 0); Sleep(0.5); delete g_pBuff; g_pBuff = NULL; return true; /读取文件进缓冲区 bool ReadFile(SOCKET sClient) if(g_pBuff!=NULL) /如果缓冲区不为空 return true; /打开文件 FILE *pFile; if(pFile = fopen(g_szNewFileName, rb)=NULL) /文件打开失败,发送错误报告 printf(Cannot find the file, reque
21、st the client input file name againn); CCSDef:TMSG_ERROR_MSG tMsgErrorMsg(MSG_OPENFILE_ERROR); :send(sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef:TMSG_ERROR_MSG), 0); return false; /传送文件长度到Client fseek(pFile,0,SEEK_END);/重定位指针到文件末尾 g_lLength=ftell(pFile);/返回文件指针相对于文件头的偏移量 printf(File Length = %dn,
22、 g_lLength); CCSDef:TMSG_FILELENGTH tMsgFileLength(g_lLength); :send(sClient,(char*)(&tMsgFileLength), sizeof(CCSDef:TMSG_FILELENGTH), 0); / 处理文件全路径名,把文件名分解出来 /磁盘号,目录,文件名,后缀名 char szDrive_MAX_DRIVE, szDir_MAX_DIR, szFname_MAX_FNAME, szExt_MAX_EXT; _splitpath(g_szNewFileName, szDrive, szDir, szFname,
23、 szExt); strcat(szFname,szExt); CCSDef:TMSG_FILENAME tMsgFileName; strcpy(tMsgFileName.szFileName, szFname); printf(Send File Name: %sn, tMsgFileName.szFileName); :send(sClient, (char*)(&tMsgFileName), sizeof(CCSDef:TMSG_FILENAME), 0); /分配缓冲区,读取文件内容 g_pBuff = new charg_lLength + 1; if (g_pBuff = NUL
24、L) return false; fseek(pFile, 0, SEEK_SET); fread(g_pBuff, sizeof(char), g_lLength, pFile); g_pBuffg_lLength = 0; fclose(pFile); return true; 【2】客户端:头文件同服务器端头文件源程序文件:cpp /*Client.cpp*/ #includeClient.h long g_lLength = 0; char* g_pBuff = NULL; char g_szFileNameMAXFILEDIRLENGTH; char g_szBuffMAX_PACK
25、ET_SIZE+1; SOCKET g_sClient; / 初始化socket库 bool InitSocket(); / 关闭socket库 bool CloseSocket(); / 把用户输入的文件路径传送到server端 bool SendFileNameToServer(); / 与server端连接 bool ConectToServer(); / 打开文件失败 bool OpenFileError(CCSDef:TMSG_HEADER *pMsgHeader); / 分配空间以便写入文件 bool AllocateMemoryForFile(CCSDef:TMSG_HEADER
26、 *pMsgHeader); / 写入文件 bool WriteToFile(CCSDef:TMSG_HEADER *pMsgHeader); / 处理server端传送过来的消息 bool ProcessMsg(); int main() while(1) InitSocket(); ConectToServer(); CloseSocket(); /system(pause); return 0; / 初始化socket库 bool InitSocket() /初始化SOCKET WSADATA wsaData; WORD socketVersion=MAKEWORD(2,2); if(:
27、WSAStartup(socketVersion,&wsaData)!=0) printf(Init socket dll errorn); exit(-1); return true; / 关闭socket库 bool CloseSocket() / 关闭套接字 :closesocket(g_sClient); / 释放winsock库 :WSACleanup(); return true; / 把用户输入的文件路径传送到server端 bool SendFileNameToServer() char szFileNameMAXFILEDIRLENGTH; printf(Input the
28、File Directory: ); /fgets(szFileName, MAXFILEDIRLENGTH, stdin); strcpy(szFileName,E:test1.A_exp); / 把文件路径发到server端 CCSDef:TMSG_FILENAME tMsgRequestFileName; strcpy(tMsgRequestFileName.szFileName, szFileName); if (:send(g_sClient, (char*)(&tMsgRequestFileName), sizeof(CCSDef:TMSG_FILENAME), 0) = SOCK
29、ET_ERROR) printf(Send File Name Error!n); exit(-1); return true; / 与server端连接 bool ConectToServer() / 初始化socket套接字 if (g_sClient = :socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = SOCKET_ERROR) printf(Init Socket Error!n); exit(-1); sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_port
30、= htons(PORT); servAddr.sin_addr.S_un.S_addr = :inet_addr(SERVER_IP); if (:connect(g_sClient, (sockaddr*)&servAddr, sizeof(sockaddr_in) = INVALID_SOCKET) printf(Connect to Server Error!n); exit(-1); / 输入文件路径传输到server端 SendFileNameToServer(); / 接收server端传过来的信息,直到保存文件成功为止 while (ProcessMsg() = true) S
31、leep(1000); return true; / 打开文件失败 bool OpenFileError(CCSDef:TMSG_HEADER *pMsgHeader) if (g_pBuff != NULL)/如果缓冲区内有数据 return true; assert(pMsgHeader != NULL); printf(Cannot find file!n); / 重新输入文件名称 SendFileNameToServer(); return true; / 分配空间以便写入文件 bool AllocateMemoryForFile(CCSDef:TMSG_HEADER *pMsgHea
32、der) assert(pMsgHeader != NULL); if (g_pBuff != NULL) return true; CCSDef:TMSG_FILENAME* pRequestFilenameMsg = (CCSDef:TMSG_FILENAME*)pMsgHeader; printf(File Name: %sn, pRequestFilenameMsg-szFileName); / 把文件的路径设置为D盘根目录下 strcpy(g_szFileName, D:); strcat(g_szFileName, test2.B_imp); /strcat(g_szFileNam
33、e, pRequestFilenameMsg-szFileName); / 查找相同文件名的文件是否已经存在,如果存在报错退出 FILE* pFile; if (pFile = fopen(g_szFileName, r) != NULL) / 文件已经存在,要求重新输入一个文件 printf(The file already exist!n); CCSDef:TMSG_ERROR_MSG tMsgErrorMsg(MSG_FILEALREADYEXIT_ERROR); :send(g_sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef:TMSG_ER
34、ROR_MSG), 0); fclose(pFile); return false; / 分配缓冲区开始接收文件,如果分配成功就给server端发送开始传送文件的要求 g_pBuff = new charg_lLength + 1; if (g_pBuff != NULL) memset(g_pBuff, 0, g_lLength + 1); printf(Now ready to get the file %s!n, pRequestFilenameMsg-szFileName); CCSDef:TMSG_CLIENT_READY tMsgClientReady; if (:send(g_s
35、Client, (char*)(&tMsgClientReady), sizeof(CCSDef:TMSG_CLIENT_READY), 0) = SOCKET_ERROR) printf(Send Error!n); exit(-1); else printf(Alloc memory for file error!n); exit(-1); return true; / 写入文件 bool WriteToFile(CCSDef:TMSG_HEADER *pMsgHeader) assert(pMsgHeader != NULL); CCSDef:TMSG_FILE* pMsgFile = (CCSDef:TMSG_FILE*)pMsgHeader; int nStart = pMsgFile-tFile.nStart; int nSize = pMsgFile-tFile.nSize; memcpy(g_pBuff + nStart, pMsgFile-tFile.szBuff, nSize); if (nStart = 0) printf(Saving f
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 新冠肺炎疫情常态化科学精准防控工作护理课件
- 年度工作计划的制定与执行跟进
- 破解社区管理难题的实施方案计划
- 研学旅行策划与管理(EEPM)(初级)等级认定考试题库大全-下(判断题)
- 女生青春期成长
- 好看的讲义模板下载
- 专题1认识自己学会学习【思维导图考点梳理考点精练】-2023年中考道德与法治一轮高效复习考点梳理归纳与精练(部编版)
- 城市更新项目交通管理方案
- 大型会议室多联机施工方案
- 2021年度教育学章节自测资料
- 2024年财务条线人员考试题库(含答案)
- 天翼云高级解决方案架构师认证资格考试题库及答案
- 2024-2030年中国水上运动皮划艇行业营销动态与竞争趋势预测报告
- 上下楼装修纠纷协议书范本
- 施工成本控制员岗位职责
- 2021-2022学年北京市房山区九年级(上)期中数学试卷【含解析】
- DB11∕1450-2017 管道燃气用户安全巡检技术规程
- 室上性心动过速-医学课件
- 《第4课 数据的安全》参考教案1
- 药品经营质量管理综合规范试题及答案
- 体育公园项目成本测算
评论
0/150
提交评论