FTP文件传输客户端程序报告.docx
《FTP文件传输客户端程序报告.docx》由会员分享,可在线阅读,更多相关《FTP文件传输客户端程序报告.docx(8页珍藏版)》请在冰豆网上搜索。
FTP文件传输客户端程序报告
FileTransferProtocolClientProgam
X1002127劉凱
1、Programexecutionresult:
程序會提示輸入資料名稱,輸入名稱之後,程序自動建立連接并發送命令,依次輸出收到的回信。
下圖即為收到的回信:
其中前兩條是歡迎信息,需要兩個recv函數接收。
2、ProgramFeatures:
a.分為一個主函數和5個小函數執行。
Main:
建立socket,調用filename和file_transfer。
Filename:
輸入資料名稱,設置STOR命令。
File_transfer:
發送命令并傳送資料,command、port和send_file。
Command:
發送命令、接收并打印回信。
Port:
計算PortY。
File_transfer發送PASV命令之後調用。
Send_file:
打開傳送資料。
函數調用關係如下圖:
程式代碼層次分明,易於閱讀和修改。
b.執行時僅需輸入需要傳送的資料名稱。
主函數調用Filename,提示輸入資料名稱,根據資料名稱設置STOR命令(即
在資料名稱之前加“STOR”,之後加“\r\n”)。
然後主函數建立指令連接,調用File_transfer進行Client端的主要操作。
File_transfer中調用Command直接發送命令,無須輸入命令字符串。
程序執行簡單,易於操作。
c. NameResolution
程式調用gethostbyname獲取伺服器IP地址。
根據IP地址去連接伺
服器。
相關代碼如下:
structhostent*server;
server=gethostbyname("cramer.ee.nthu.edu.tw");
//獲取IP。
servaddr1.sin_addr=*((structin_addr*)server->h_addr);
//將IP連接到socket
servaddr2.sin_addr=*((structin_addr*)server->h_addr);
有進行NameResolution。
3.Sourcecode
#include
#include
#include
#include
#include
#include
#defineMAXLEN1024
//PS:
執行時僅需輸入要傳送的資料名稱即可,程序會自動發送命令并輸出來自服務器的回信。
//這些變量在多個函數中需要使用,因此定義在程序開頭。
charRcvBuf[MAXLEN];
intn;
SOCKETa,b;
//a用於建立連線,b用於傳送資料。
SOCKADDR_INservaddr1,servaddr2;
charname[30],stor[30]="STOR";
//command用於向FTP服務器發送命令,然後接收回信并打印出來。
intcommand(char*message)
{
send(a,message,strlen(message),0);
n=recv(a,RcvBuf,MAXLEN,0);
RcvBuf[n]='\0';
//在接收緩衝區的末尾加字符串結束符號。
printf("%s\n\n",RcvBuf);
}
//發送PSAV命令之後,port將收到的信息中的porty轉換為整數。
如接收“227EnteringPassiveMode(140,114,26,104,68,245)”,則p1=245,p2=68。
intport()
{
inti=0,j=0,k=0,p,p1=0,p2=0;
while(RcvBuf[i]!
=')')i++;
//用while找到右括號,然後依次求p1、p2,從右往左進行計算。
for(i=i-1;j<1;i--)//計算p1
{
if(RcvBuf[i]==',')j++;
else
{
p=RcvBuf[i]-'0';//將字符轉化為數字.
p1=p1+pow(10,k)*p;
k++;
}
}
k=0;
for(;j<2;i--)//計算p2
{
if(RcvBuf[i]==',')j++;
else
{
p=RcvBuf[i]-'0';
p2=p2+pow(10,k)*p;
k++;
}
}
returnp=p1+p2*256;
}
//傳送資料的連接建立之後,用於發送資料。
intsend_file()
{
charSendBuf[MAXLEN];
FILE*p;
intFileSize;
p=fopen(name,"rb");//打開資料。
fseek(p,0L,SEEK_END);
FileSize=ftell(p);//用fseek和ftell計算資料大小。
fread(SendBuf,FileSize,1,p);
//將要發送的資料寫入發送緩衝區。
fclose(p);
send(b,SendBuf,FileSize,0);
closesocket(b);
//發送文件之後應及時關閉資料連接,不然收不到“226...."。
return0;
}
//主函數調用此函數進行Client端的主要操作。
intfile_transfer()
{
intport_y,i=0;
while(i<2)/while/用於接收歡迎信息。
{
n=recv(a,RcvBuf,MAXLEN,0);
RcvBuf[n]='\0';
printf("%s\n\n",RcvBuf);
i++;
}
command("USEREE3650\r\n");
//命令不採用鍵盤輸入,調用command函數發送命令和輸出收到的信息。
command("PASS2012EE3650\r\n");
command("MKDx1002127\r\n");
command("CWD/X1002127\r\n");
command("PASV\r\n");
port_y=port();//調用port函數計算收到的porty。
command("TYPEI\r\n");
servaddr2.sin_port=htons(port_y);
connect(b,(SOCKADDR*)&servaddr2,sizeof(servaddr2));
//建立資料連接。
command(stor);
send_file();//調用send_file發送文件。
n=recv(a,RcvBuf,MAXLEN,0);
RcvBuf[n]='\0';
printf("%s\n\n",RcvBuf);
return0;
}
//輸入要傳送的資料名稱並且將STOR命令設置好。
intfilename()
{
printf("Pleaseinputthenameofthefileyouwanttotransfer:
\n");
scanf("%s",name);
strcat(stor,name);//設置STOR命令。
strcat(stor,"\r\n");
return0;
}
intmain()
{
WSADATAwsaData;
Struchostent*server;//此結構體用於nameresolution
WSAStartup(MAKEWORD(2,2),&wsaData);
server=gethostbyname("cramer.ee.nthu.edu.tw");//調用gethostbyname進行nameresolution。
a=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
b=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
servaddr1.sin_family=AF_INET;
servaddr1.sin_port=htons(21);
servaddr1.sin_addr=*((structin_addr*)server->h_addr);
//將gethostbyname返回的ip信息連接到socket.
servaddr2.sin_family=AF_INET;
servaddr2.sin_addr=*((structin_addr*)server->h_addr);
filename();//用於輸入名稱,并設置STOR命令。
connect(a,(SOCKADDR*)&servaddr1,sizeof(servaddr1));
file_transfer();//調用file_transfer完成client端的操作。
closesocket(a);
WSACleanup();
system("pause");
return0;}
//PS:
執行時僅需輸入要傳送的資料名稱即可,程序會自動發送命令并輸出來自服務器的回信。