TCP协议实现文件传输
《TCP协议实现文件传输》由会员分享,可在线阅读,更多相关《TCP协议实现文件传输(10页珍藏版)》请在装配图网上搜索。
1、TCP协议实现文件传输使用TCP协议实现传输文件程序分为发送端和接收端。首先在传输文件数据之前,发送端会把将装有文件名称和文件长度等信息的数据包发送至接收端。接收端收到文件名称和文件长度信息后会创建好空白文件。接着开始传输文件数据。下面介绍实现功能的主要过程:1.创建套接字、绑定、监听、连接、接受连接创建TCP协议的套接字m_Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(SOCKET_ERROR=m_Socket)AfxMessageBox(CreateSocketError!,0,0);/绑定与监听SOCKADDR_INaddrSrv;a
2、ddrSrv.sin_addr.s_addr=inet_addr(sIP);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(Port);intret=bind(m_Socket,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR);if(ret=SOCKET_ERROR)AfxMessageBox(BindSocketError!,0,0);/连接SOCKADDR_INServerAddr;ServerAddr.sin_addr.s_addr=inet_addr(ServerAddr_in);ServerAddr.sin_
3、family=AF_INET;ServerAddr.sin_port=htons(ServerPort);intResult=connect(m_Socket,(structsockaddr*)&ServerAddr,sizeof(structsockaddr);if(SOCKET_ERROR=Result)AfxMessageBox(ConnetFailed!);/接受连接SOCKADDR_INClientAddr;intlen=sizeof(SOCKADDR_IN);SOCKETClientSock=accept(m_Socket,(structsockaddr*)&ClientAddr,
4、&len);if(SOCKET_ERROR=ClientSock)AfxMessageBox(AcceptFailed!);2.声明宏和结构体声明套接字缓冲区和一次发送文件数据的缓冲区大小#defineSOCKET_BUFF80000/套接字缓冲区大小#definePACK_BUFF50000/数据包缓冲区大小声明文件I/O缓冲区和最大文件路径长度#defineFILE_NAME_MAX100/文件路径最大长度#defineFILE_IO_BUFFPACK_BUFF文件IO缓冲区/文件信息typedefstruct_FileInforu_longulFileLen;charsFileNameF
5、ILE_NAME_MAX;_FileInfor;/数据包typedefstruct_DataPackcharcType;D为数据M为文件信息intnPackLen;/数据包缓冲区charsContentPACK_BUFF;u_longnPosition;intnContentLen;/数据在文件中的位置/数据字节数FileInforFileInfor;/文件信息_DataPack;3.发送端/发送线程需要的全局变量charsPathFILE_NAME_MAX;/文件地址u_longFileByteCount;/文件大小SOCKETClientSocket;/(1) 设置套接字发送缓冲区大小,在
6、32位WindowsXP环境下,系统为每个套接字分配的默认发送数据缓冲区为8192字节。由于传输的文件很大,可能几十兆,或者更大。那么系统为每个套接字分配的默认缓冲区显然过小。为此在创建套接字之后,需要修改套接字发送数据缓冲尺寸。在这里我修改为80k,差不多可以够用了。/设置套接字发送缓冲区intnBuf=SOCKET_BUFF;intnBufLen=sizeof(nBuf);intnRe=setsockopt(ClientSock,SOL_SOCKET,SO_SNDBUF,(char*)&nBuf,nBufLen);if(SOCKET_ERROR=nRe)AfxMessageBox(sets
7、ockopterror!);/检查缓冲区是否设置成功nRe=getsockopt(ClientSock,SOL_SOCKET,SO_SNDBUF,(char*)&nBuf,&nBufLen);if(SOCKET_BUFF!=nBuf)AfxMessageBox(检查缓冲区:setsockopterror!);(2) 测量文件大小并发送文件大小和名称给客户端首先使用C库函数对源文件进行测量/得到文件地址LPTSTRlpPath=m_sPath.GetBuffer(m_sPath.GetLength();/打开文件FILE*File=fopen(lpPath,rb);if(NULL=File)Af
8、xMessageBox(打开文件失败!);/测量文件大小charBuffPACK_BUFF;u_longulFaceReadByte;FileByteCount=0;fseek(File,0,SEEK_SET);while(!feof(File)ulFaceReadByte=fread(Buff,1,1,File);FileByteCount+=ulFaceReadByte;/关闭文件intnRe=fclose(File);if(nRe)AfxMessageBox(关闭文件失败!);此时以获取源文件的长度,我们将文件长度和文件名称放到数据包中,设置数据包为M类型。/打包_DataPackPac
9、k;Pack.cType=M;Pack.nPackLen=sizeof(Pack);/取得文件名ZeroMemory(Pack.FileInfor.sFileName,FILE_NAME_MAX);GetFIieNameFromPath(lpPath,Pack.FileInfor.sFileName);Pack.FileInfor.ulFileLen=FileByteCount;接着使用send()将打包完成的数据包发送给接收端,把发送线程的全局变量初始化,并创建发送线程,文件数据将由发送线程负责发送/发送数据包文件大小和名称nRe=send(m_ClientSockFd.fd_array0,
10、(char*)&Pack,Pack.nPackLen,0);if(SOCKET_ERROR=nRe)AfxMessageBox(SendFileSizeFailed!);/线程准备全局变量strcpy(sPath,m_sPath);ClientSocket=m_ClientSockFd.fd_array0;/启动线程发送文件DWORDID;m_hSendThread=CreateThread(0,0,SendDataThrad,0,0,&ID);(3) 发送文件数据线程。先打开源文件,为了一次读取大量数据将文件缓冲区设置为FILE_IO_BUFF大小,然后将读取的数据打包并发送。这样不断地读、
11、不断地发送,直到将整个文件发送完为止DWORD_stdcallCServerDlg:SendDataThrad(LPVOIDLpP)/打开文件FILE*File=fopen(sPath,rb);if(NULL=File)AfxMessageBox(SendDataThrad中打开文件失败!);return1;/设置文件缓冲区intnBuff=FILE_IO_BUFF;if(setvbuf(File,(char*)&nBuff,_IOFBF,sizeof(nBuff)AfxMessageBox(设置文件缓冲区失败!);/读取文件数据并发送u_longulFlagCount=0;/记录读了多少数据
12、u_longFaceReadByte=0;/一次实际读取的字节数charsBuffPACK_BUFF;ZeroMemory(sBuff,PACK_BUFF);fseek(File,0,SEEK_SET);while(!feof(File)FaceReadByte=fread(sBuff,1,PACK_BUFF,File);/打包_DataPackDataPack;DataPack.cType=D;DataPack.nPackLen=sizeof(DataPack);DataPack.nContentLen=FaceReadByte;CopyMemory(DataPack.sContent,sB
13、uff,FaceReadByte);DataPack.nPosition=ulFlagCount;/发送intnResult=send(ClientSocket,(char*)&DataPack,DataPack.nPackLen,0);if(SOCKET_ERROR=nResult)AfxMessageBox(SendDataThrad中发送数据失败!);elseulFlagCount+=FaceReadByte;/记录发送字节数AfxMessageBox(发送结束);/关闭intnRe=fclose(File);if(nRe)AfxMessageBox(SendDataThrad中关闭文件
14、失败!);return0;4.接收端/接收线程用的全局变量_FileInforFileInfor;/文件信息u_longulWriteByte;/记录总共写入的字节charlpPathFILE_NAME_MAX;/文件路径charsFilePathAndNameFILE_NAME_MAX;/完整的文件路径(1)设置套接字接收缓冲区大小。/设置套接字接收缓冲区intnBuf=SOCKET_BUFF;intnBufLen=sizeof(nBuf);SOCKETClientSock=m_Sock.GetSocket();intnRe=setsockopt(ClientSock,SOL_SOCKET,
15、SO_RCVBUF,(char*)&nBuf,nBufLen);if(SOCKET_ERROR=nRe)AfxMessageBox(setsockopterror!);/检查缓冲区是否设置成功nRe=getsockopt(ClientSock,SOL_SOCKET,SO_RCVBUF,(char*)&nBuf,&nBufLen);if(SOCKET_BUFF!=nBuf)AfxMessageBox(检查缓冲区:setsockopterror!);(2)接收文件信息和文件数据线程。先判断数据包是属于文件信息还是文件类型,如果是文件信息就根据信息创建空文件,如果是文件数据就将数据已追加的方式写进目
16、的文件中。DWORD_stdcallCClientDlg:ReceiveDataPro(LPVOIDLpP)CSocket_Win32*pCSock=(CSocket_Win32*)LpP;u_longulWriteByteCount=0;while(1)_DataPackDataPack;ZeroMemory(&DataPack,sizeof(DataPack);if(!(*pCSock).Receive(&DataPack,sizeof(DataPack)AfxMessageBox(ReceiveDataPackFailed!);/判断数据包类型if(M=DataPack.cType)/包
17、为文件信息/接收文件信息FileInfor.ulFileLen=DataPack.FileInfor.ulFileLen;/获取文件长度strcpy(FileInfor.sFileName,DataPack.FileInfor.sFileName);/获取文件名称/得到文件目录charsFilePathFILE_NAME_MAX;ZeroMemory(sFilePath,FILE_NAME_MAX);strcpy(sFilePath,lpPath);strcat(sFilePath,FileInfor.sFileName);strcat(sFilePathAndName,sFilePath);
18、/保存完整的文件路径/创建文件SECURITY_ATTRIBUTESattr;attr.nLength=FileInfor.ulFileLen;attr.lpSecurityDescriptor=NULL;HANDLEhRe=CreateFile(sFilePath,GENERIC_WRITE,FILE_SHARE_WRITE,&attr,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);if(INVALID_HANDLE_VALUE=hRe)AfxMessageBox(创建文件失败!);boolbRe=:CloseHandle(hRe);/可以开始接受文件bIsS
19、tartReceive=true;elseif(D=DataPack.cType)/包为文件数据/打开文件charsPathFILE_NAME_MAX;strcpy(sPath,sFilePathAndName);FILE*File=fopen(sPath,ab);if(0=File)AfxMessageBox(打开文件失败!);/设置文件缓冲区intnBuff=FILE_IO_BUFF;if(setvbuf(File,(char*)&nBuff,_IOFBF,sizeof(nBuff)AfxMessageBox(设置文件缓冲区失败!);/定位文件u_longnPosition=DataPac
20、k.nPosition;intnRe=fseek(File,nPosition,SEEK_SET);if(nRe)AfxMessageBox(SendDataThrad中定位失败!);/写文件u_longnNumberOfBytesWritten=fwrite(&DataPack.sContent,1,DataPack.nContentLen,File);if(DataPack.nContentLen!=nNumberOfBytesWritten)AfxMessageBox(写文件失败!);elseulWriteByteCount+=nNumberOfBytesWritten;fflush(File);/清除文件缓冲区/关闭文件nRe=fclose(File);if(nRe)AfxMessageBox(关闭文件失败!);if(ulWriteByteCount=FileInfor.ulFileLen)AfxMessageBox(接收结束);break;return0;
- 温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。