用Socket编程实现FTPWord格式文档下载.docx
- 文档编号:8363949
- 上传时间:2023-05-11
- 格式:DOCX
- 页数:11
- 大小:172.02KB
用Socket编程实现FTPWord格式文档下载.docx
《用Socket编程实现FTPWord格式文档下载.docx》由会员分享,可在线阅读,更多相关《用Socket编程实现FTPWord格式文档下载.docx(11页珍藏版)》请在冰点文库上搜索。
WindowsSockets实现,一个WindowsSockets实现是指实现了WindowsSockets规范所描述的全部功能的一套软件。
一般通过DLL文件来实现。
Windows环境下进行网络程序设计的最基本方法是应用WindowsSockets来实现,通过使用MFC提供的WindowsSockets类,能够很好的完成FTP的功能。
连接管理:
数据连接有3大用途:
(1)从客户向服务器发送一个文件
(2)从服务器向客户发送一个文件
(3)从服务器向客户发送文件或目录列表。
每一个数据连接对传输一个文件或目录序列都要建立一个新的连接。
(1)客户发出命令要求建立数据连接
(2)客户在客户主机上未数据连接选择一个固定的端口号
(3)客户使用PORT命令从控制连接上把端口号发给服务器。
(4)服务器在控制连接上接收端口号,并向客户端主机上的端口发出主动打开,服务器的数据连接使用端口21。
基本套接字
为了更好说明套接字编程原理,给出几个基本的套接字,在以后的篇幅中会给出更详细的使用说明。
1、创建套接字——socket()
功能:
使用前创建一个新的套接字
格式:
SOCKETPASCALFARsocket(intaf,inttype,intprocotol);
参数:
af:
通信发生的区域
type:
要建立的套接字类型
procotol:
使用的特定协议
2、指定本地地址——bind()
将套接字地址与所创建的套接字号联系起来。
intPASCALFARbind(SOCKETs,conststructsockaddrFAR*name,intnamelen);
s:
是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。
其它:
没有错误,bind()返回0,否则SOCKET_ERROR
地址结构说明:
structsockaddr_in
{
shortsin_family;
//AF_INET
u_shortsin_port;
//16位端口号,网络字节顺序
structin_addrsin_addr;
//32位IP地址,网络字节顺序
charsin_zero[8];
//保留
}
3、建立套接字连接——connect()和accept()
共同完成连接工作
intPASCALFARconnect(SOCKETs,conststructsockaddrFAR*name,intnamelen);
SOCKETPASCALFARaccept(SOCKETs,structsockaddrFAR*name,intFAR*addrlen);
同上
4、监听连接——listen()
用于面向连接服务器,表明它愿意接收连接。
intPASCALFARlisten(SOCKETs,intbacklog);
5、数据传输——send()与recv()
数据的发送与接收
intPASCALFARsend(SOCKETs,constcharFAR*buf,intlen,intflags);
intPASCALFARrecv(SOCKETs,constcharFAR*buf,intlen,intflags);
buf:
指向存有传输数据的缓冲区的指针。
6、多路复用——select()
用来检测一个或多个套接字状态。
intPASCALFARselect(intnfds,fd_setFAR*readfds,fd_setFAR*writefds,
fd_setFAR*exceptfds,conststructtimevalFAR*timeout);
readfds:
指向要做读检测的指针
writefds:
指向要做写检测的指针
exceptfds:
指向要检测是否出错的指针
timeout:
最大等待时间
7、关闭套接字——closesocket()
关闭套接字s
BOOLPASCALFARclosesocket(SOCKETs);
FTP下载文件流程
FTP服务端和客户端之间存在两中连接:
一中用于传输FTP命令(命令必须由客户端主动发起),连接始终存在;
另一中用于向客户端传输数据,每当要传输文件或目录文件列表信息时则建立一个数据连接,数据传输完毕立即断开。
数据连接有两种建立方式:
客户端监听某端口,服务器主动发起数据连接。
服务器监听某端口,客户端主动发起数据连接。
下载文件之前首先需要登陆,登陆的状态图如图2所示。
如果前面发送的命令均得到成功响应,则表示服务器数据准备完毕。
下面需要做的是与服务建立数据连接,开始接受数据,并将接收到的数据保存在本地文件中,直到接收完毕后断开数据连接,下载完毕。
通过访问全局变量获得FTP服务器IP地址和端口号,以及登陆的用户名和密码,登陆服务器。
为了实现FTP下载文件能成功,我觉得用代码和图片解释比较好,但文字描述不清楚,所以用代码的比较多,虽然觉得不好,但我只能这样。
流程图
流程图1
(一)FTP客户端的主要代码
1.头文件
#include"
stdafx.h"
ListItem.h"
#ifdef_DEBUG
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#definenewDEBUG_NEW
#endif
2.创建ParseLine()函数
BOOLCListItem:
:
ParseLine(CStringstrLine)
if(strLine.IsEmpty())
returnFALSE;
charch=strLine.GetAt(0);
if(ch=='
d'
||ch=='
D'
){
m_bDirectory=TRUE;
}
else
if(ch=='
-'
)
m_bDirectory=FALSE;
else{
if(strLine.Find("
<
DIR>
"
)!
=-1||strLine.Find("
dir>
=-1)
m_bDirectory=TRUE;
else
m_bDirectory=FALSE;
if(strLine.GetLength()<
40)
returnFALSE;
m_strName=strLine.Mid(39);
m_strDate=strLine.Left(18);
m_strName.TrimLeft();
m_strName.TrimRight();
returnTRUE;
}
m_bSec=0;
for(inti=0;
i<
9;
i++){
ch=strLine.GetAt(i);
m_bSec|=0x01;
m_bSec<
=1;
m_strSec=strLine.Mid(1,9);
intndx=strLine.Find('
'
);
if(ndx==-1){
if(strLine.GetLength()>
56)
ndx=51;
else
returnFALSE;
m_index=ndx;
m_strName=strLine.Mid(ndx+3);
m_strName.TrimLeft();
m_strName.TrimRight();
m_strDate=strLine.Mid(ndx-9,12);
returnTRUE;
(二)客户端运行后的界面
图2
上面的图是运行后在修改了用户名和密码,查出所需要的文件的I盘和文件名。
客户端运行后看到的的服务器端地址是所用电脑的
(三)FTP服务器端代码
1.Socket编程中的Server()函数
UINTServerThread(LPVOIDlpParameter)
SOCKETsListen,sAccept;
SOCKADDR_INinetAddr;
DWORDdwFlags;
DWORDdwRecvBytes;
CServer*server=(CServer*)lpParameter;
2.创建第一个手动重置对象
if((g_events[0]=WSACreateEvent())==WSA_INVALID_EVENT)
{
printf("
错误:
WSACreateEventfailedwitherror%d\n"
WSAGetLastError());
return0;
3.创建一个线程处理请求
AfxBeginThread(ProcessTreadIO,(LPVOID)server);
if(CreateThread(NULL,0,ProcessTreadIO,(void*)server,0,&
dwThreadId)==NULL)
CreateThreadfailedwitherror%d\n"
GetLastError());
}
g_dwEventTotal=1;
while(!
server->
m_bStop)
//处理入站连接
if((sAccept=accept(sListen,NULL,NULL))==INVALID_SOCKET)
acceptfailedwitherror%d\n"
//回传欢迎消息
if(!
WelcomeInfo(sAccept))break;
//设置ftp根目录
SetCurrentDirectory(server->
m_Directory))break;
4.创建一个新的SOCKET_INF结构处理接受的数据socket.
if((g_sockets[g_dwEventTotal]=(LPSOCKET_INF)
GlobalAlloc(GPTR,sizeof(SOCKET_INF)))==NULL)
GlobalAlloc()failedwitherror%d\n"
5.初始化新的SOCKET_INF结构
charbuff[DATA_BUFSIZE];
memset(buff,0,DATA_BUFSIZE);
g_sockets[g_dwEventTotal]->
wsaBuf.buf=buff;
wsaBuf.len=DATA_BUFSIZE;
s=sAccept;
memset(&
(g_sockets[g_dwEventTotal]->
o),0,sizeof(OVERLAPPED));
dwBytesSend=0;
dwBytesRecv=0;
g_sockets[g_dwEventTotal]->
nStatus=WSA_RECV;
//接收
6.下载数据的有关代码
//已经有数据传递
if(pSI->
nStatus==WSA_RECV)
……………..
{
if(!
g_bLoggedIn)
{
if(server->
LoginIn(pSI)==LOGGED_IN)
g_bLoggedIn=TRUE;
}
else
if(server->
DealCommand(pSI)==FTP_QUIT)
continue;
}
//缓冲区清除
memset(pSI->
buffRecv,0,sizeof(pSI->
buffRecv));
pSI->
pSI->
dwBytesSend+=dwBytesTransferred;
//继续接收以后到来的数据
if(server->
RecvReq(pSI)==-1)
return-1;
………………………….
//接受数据
intCServer:
RecvReq(LPSOCKET_INFpSI)
staticDWORDdwRecvBytes=0;
pSI->
…………
7.取得文件列表信息,并转换成字符串
BOOLbDetails=strstr(szCmd,"
LIST"
)?
TRUE:
FALSE;
UINTnStrLen=FileListToString(buff,sizeof(buff),bDetails);
if(!
bPasv)
………………
if(ReadFileToBuffer(szFile,buff,nFileSize)==(DWORD)nFileSize)
{
//处理DataFTP连接
Sleep(10);
if(bPasv)
DataSend(sAccept,buff,nFileSize);
closesocket(sAccept);
…………………
(四)FTP服务器端运行后的界面
图3
上面得图是在添加用户名等,为了能下载自己的文件。
端口设定为21是固定的。
下面的图是添加用户后在点击HESY用户和开始服务后所得界面。
图4
四、调试结果
在点击开始服务后就转到客户端运行所得界面上,然后点击CONNECT会连接到服务器端,会登陆到用户名以及所需要下载的文件。
图5
运行环境硬件环境:
CPU的主频在200MHz以上、内存在64MB以上。
软件平台:
操作系统为Windows98/Me/NT/2000/XP(推荐使用Windows2000/XP),调试环境为VisualC++6.0及其以上版本(如果不做说明,则默认为VisualC++6.0)。
五、心得体会
由于学习的也是服务器端与客户端之间的通信,并且老师讲的和做的都成功,所以觉得在用Socket编程实现FTP中服务器端与客户端会较方便,服务器端的代码很多,我把很多有用的都省了。
运行时还经常出错,我的编程较差,改了之后运行后还需要调试结果和把界面的一些信息进行修改。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Socket 编程 实现 FTP