




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、第ChpNum章 文件傳輸協(xié)議的C語言實(shí)現(xiàn)1設(shè)計(jì)目的本設(shè)計(jì)旨在利用Winsock 2.0簡單實(shí)現(xiàn)FTP(File Transfer Protocol,文件傳輸協(xié)議)的客戶端和服務(wù)器端程序。通過完成此設(shè)計(jì),了解Winsock API函數(shù)調(diào)用方法和一般網(wǎng)絡(luò)應(yīng)用程序的編程方法,理解FTP協(xié)議,掌握C語言設(shè)計(jì)FTP協(xié)議軟件的基本技術(shù),為將來開發(fā)其他通信協(xié)議軟件打下堅(jiān)實(shí)基礎(chǔ)。 2 設(shè)計(jì)準(zhǔn)備(1)連入同一局域網(wǎng)的PC,每人一臺。(2)PC裝有Windows操作系統(tǒng)、Visual C+ 6.0編譯器及開發(fā)手冊MSDN 6.0。3關(guān)鍵技術(shù)3.1 文件傳輸協(xié)議介紹FTP 是File Transfer Proto
2、col(文件傳輸協(xié)議)的英文簡稱,用于Internet上的控制文件的雙向傳輸。在實(shí)現(xiàn)的層面上,F(xiàn)TP又可理解為一個(gè)可用于文件傳輸?shù)目蛻魴C(jī)/服務(wù)器系統(tǒng),該系統(tǒng)包括客戶機(jī)端程序和服務(wù)器端程序,客戶端和服務(wù)器端通信規(guī)則為FTP協(xié)議。用戶通過客戶機(jī)程序向服務(wù)器程序發(fā)出命令請求,服務(wù)器程序執(zhí)行用戶所發(fā)出的命令,并將執(zhí)行的結(jié)果返回到客戶機(jī)。比如說,用戶發(fā)出一條命令,要求服務(wù)器向用戶傳送某一個(gè)文件的一份拷貝,服務(wù)器會(huì)響應(yīng)這條命令,將指定文件送至用戶的機(jī)器上??蛻魴C(jī)程序接收到這個(gè)文件,將其存放在用戶目錄中。在通信協(xié)議的分層模型中,文件傳輸協(xié)議是在TCP(Transmission control Protoco
3、l,傳輸控制協(xié)議)之上的一個(gè)應(yīng)用層協(xié)議,應(yīng)用程序之間的通信需要用到傳輸層提供的字節(jié)流透明無誤傳輸服務(wù)。Windows操作系統(tǒng)具有TCP/IP協(xié)議棧,應(yīng)用程序可通過Winsock API函數(shù)的調(diào)用實(shí)現(xiàn)端到端透明數(shù)據(jù)鏈接的建立。3.2 Winsock API介紹 因特網(wǎng)(Internet)最初是基于Unix的,而Sockets(套接字)是Unix第一個(gè)支持TCP/IP協(xié)議棧的網(wǎng)絡(luò)API,最早于1982年8月隨4.2 BSD版Unix推出,常被稱為Berkeley sockets(伯克利套接字)。Winsock(Windows Sockets API)是從Sockets移植過來的TCP/IP編程的低
4、級Windows API。Winsock分1.1版和2.x版,從Windows 98開始使用2.x版。Winsock與windows操作系統(tǒng)的關(guān)系如圖ChpNum-1所示。操作系統(tǒng)實(shí)現(xiàn)了TCP/IP協(xié)議棧,(包括傳輸層協(xié)議TCP及UDP;網(wǎng)絡(luò)層協(xié)議IP、ICMP及IGMP;鏈路層協(xié)議ARP和RAR),該模塊的相關(guān)功能以動(dòng)態(tài)鏈接庫的形式被應(yīng)用程序調(diào)用。操作系統(tǒng)接受網(wǎng)卡驅(qū)動(dòng)程序的注冊,網(wǎng)卡驅(qū)動(dòng)程序本質(zhì)上是一套控制網(wǎng)卡硬件收發(fā)報(bào)文的函數(shù),也是以動(dòng)態(tài)鏈接庫的形式被調(diào)用。物理通信介質(zhì)是指網(wǎng)卡驅(qū)動(dòng)芯片及其外圍電路,完成鏈路層數(shù)據(jù)幀的封裝/解封、發(fā)送/接收等功能。圖ChpNum1 Winsock與操作系統(tǒng)的
5、關(guān)系套接字可看作是不同主機(jī)間的進(jìn)程進(jìn)行雙向通信的虛擬管道端點(diǎn):網(wǎng)絡(luò)中兩臺主機(jī)各自在自己機(jī)器上建立通信的端點(diǎn)-套接字,然后使用套接字進(jìn)行數(shù)據(jù)通信。一個(gè)套接字包含五個(gè)基本元素:協(xié)議類型、本地IP地址、本地端口、遠(yuǎn)端IP地址和遠(yuǎn)端端口。在操作系統(tǒng)中,套接字是一種系統(tǒng)資源,應(yīng)用程序使用時(shí)應(yīng)向操作系統(tǒng)申請或注冊,使用結(jié)束后應(yīng)用程序應(yīng)釋放該該套接字。和其他系統(tǒng)資源一樣,操作系統(tǒng)為套接字分配一個(gè)唯一的ID(在Windows中被稱作句柄)。根據(jù)網(wǎng)絡(luò)通信的特征,套接字分為三類:流套接字(SOCK_STREAM)、數(shù)據(jù)報(bào)套接字(SOCK_DGRAM)和原始套接字(SOCK_RAW)。流套接字是面向連接的,它提供雙
6、向的、有序的、無差錯(cuò)、無重復(fù)并且無記錄邊界的數(shù)據(jù)流服務(wù),適用于處理大量數(shù)據(jù),提供可靠的服務(wù)。數(shù)據(jù)報(bào)套接字是無連接的,它支持雙向的數(shù)據(jù)傳輸,具有開銷小、數(shù)據(jù)傳輸效率高的特點(diǎn),但不保證數(shù)據(jù)傳輸?shù)目煽啃?、有序性和無重復(fù)性,適合少量數(shù)據(jù)傳輸、以及時(shí)間敏感的音/視頻等多媒體數(shù)據(jù)傳輸。原始套接字(SOCK_RAW)可以用作對底層協(xié)議(如IP或ICM)的直接訪問。Winsock網(wǎng)絡(luò)應(yīng)用程序利用API 函數(shù)(如accept、send、recv等函數(shù))進(jìn)行I/O操作時(shí)有阻塞和非阻塞兩種模式。若要獲取的資源還沒有到達(dá)(如:接收緩沖區(qū)中沒有數(shù)據(jù)提供給recv函數(shù)),在阻塞模式下,執(zhí)行I/O操作的Winsock函數(shù)在
7、I/O操作完成前會(huì)一直等待下去,不會(huì)立即返回;而在非阻塞模式下,該函數(shù)不管I/O操作有沒有完成都會(huì)立即返回,若未完成一般會(huì)返回錯(cuò)誤碼WSAWOULDBLOCK,意味著必須重新進(jìn)行嘗試。阻塞模式與非阻塞模式比較,從編程角度來說,前者更便于使用,但從程序運(yùn)行的效率來說,由于阻塞調(diào)用后會(huì)使得所在的線程(如果是主線程那么就是整個(gè)程序)等待在該I/O操作上,因此后者效率更高。默認(rèn)情況下,這些I/O操作工作于阻塞模式。在阻塞模式下使用Winsock 2的API庫函數(shù)進(jìn)行數(shù)據(jù)報(bào)套接字編程的過程如圖ChpNum-2所示。在服務(wù)器端,先調(diào)用WSASartup函數(shù)進(jìn)行初始化,初始化完成后調(diào)用Socket函數(shù)創(chuàng)建一
8、個(gè)Socket s,再調(diào)用bind函數(shù)將該套接字綁定到某個(gè)特定端口,接下來調(diào)用Listen函數(shù)啟動(dòng)監(jiān)聽并調(diào)用Accept函數(shù)接收客戶連接,若客戶連接請求未及時(shí)到達(dá),則Accept函數(shù)處于阻塞狀態(tài)。Accept函數(shù)為客戶端的連接請求創(chuàng)建一個(gè)新的套接字S1,在以后的通信中,服務(wù)器利用套接字s1與客戶端進(jìn)行數(shù)據(jù)雙向傳輸。通信結(jié)束時(shí),服務(wù)器可以采用Closesocket函數(shù)釋放套接字,并可調(diào)用WSAClearup釋放Winsock DLL??蛻魴C(jī)是連接的請求的發(fā)起者,在創(chuàng)建Socket之后直接通過調(diào)用Connect發(fā)起連接請求,成功后即可以利用該Socket進(jìn)行雙向通信了。下面對Winsock 2提供
9、的主要接口函數(shù)逐一進(jìn)行介紹。 圖ChpNum-2 基于TCP的網(wǎng)絡(luò)應(yīng)用程序(1)WSAStartup()函數(shù)和WSACleanup()函數(shù)由于Winsock 2提供的API服務(wù)是以動(dòng)態(tài)鏈接庫ws2_32.dll實(shí)現(xiàn)的,所以必須先調(diào)用WSAStartup() 函數(shù)對ws2_32.dll進(jìn)行加載初始化,協(xié)商Winsock的版本支持,并分配必要的資源。在應(yīng)用程序關(guān)閉套接字后,還應(yīng)調(diào)用WSACleanup( )函數(shù)來終止和卸載動(dòng)態(tài)鏈接庫ws2_32.dll,釋放資源。(2)socket()函數(shù)服務(wù)進(jìn)程和客戶進(jìn)程在通信前必須創(chuàng)建各自的套接字,然后才能用相應(yīng)的套接字進(jìn)行發(fā)送、接收操作,實(shí)現(xiàn)數(shù)據(jù)的傳輸。服務(wù)
10、進(jìn)程總是先于客戶進(jìn)程啟動(dòng),服務(wù)進(jìn)程和客戶進(jìn)程調(diào)用socket() 函數(shù)創(chuàng)建套接字。(3)bind( ) 函數(shù)當(dāng)用socket( )創(chuàng)建套接字后,它便存在于一個(gè)名字空間(地址族)中,但并未賦名。bind ( )函數(shù)通過給一個(gè)未命名套接字分配一個(gè)本地名字(主機(jī)地址/端口號)來為套接字建立本地捆綁??蛻舳艘话汶[式地向操作系統(tǒng)請求一個(gè)隨機(jī)的未使用過的臨時(shí)端口號,跟自己的IP地址一起,與所創(chuàng)建的套接字建立聯(lián)系,由于該臨時(shí)端口號客戶端程序事先是不確定的,因此不顯式地使用綁定函數(shù)。(4)listen( )函數(shù)調(diào)用listen( )函數(shù)對服務(wù)器上套接字啟動(dòng)監(jiān)聽,即允許客戶連接請求開始排隊(duì)。(5)accept(
11、 )函數(shù)服務(wù)器設(shè)置監(jiān)聽工作方式后,通過調(diào)用 accept( ) 函數(shù)使套接字等待接受客戶連接。如果已有連接請求到來,該函數(shù)會(huì)返回一個(gè)新的套接字描述符,它對應(yīng)于已經(jīng)接受的那個(gè)客戶端連接。對于該客戶機(jī)后續(xù)的所有操作,都應(yīng)使用這個(gè)新套接字。至于原來那個(gè)監(jiān)聽套接字,它仍然用于接受其他客戶機(jī)連接,繼續(xù)處于監(jiān)聽模式。(6)connect( )函數(shù)客戶端利用 connect( ) 函數(shù)和服務(wù)器建立一個(gè)端到端的連接。(7)closesocket( )函數(shù)網(wǎng)絡(luò)通信任務(wù)完成后,利用本函數(shù)釋放套接字占用的所有資源。4 軟件設(shè)計(jì) 本設(shè)計(jì)客戶端及服務(wù)器端均采用單線程實(shí)現(xiàn),命令和數(shù)據(jù)的傳輸在同一個(gè)Socket鏈接上進(jìn)行。
12、客戶端支持DIR(遠(yuǎn)端文件夾查詢)、GET(文件下載)、PUT(文件上傳)、PWD(遠(yuǎn)端當(dāng)前路徑查詢)、CD(遠(yuǎn)端當(dāng)前路徑設(shè)置)、MD(遠(yuǎn)端文件夾創(chuàng)建)、DEL(遠(yuǎn)端文件刪除)等7個(gè)常用FTP命令。 用戶命令格式為“命令字 路徑名/文件名”,如下載當(dāng)前目錄下的test.txt文件,則用戶在控制臺界面輸入的命令格式為“GET test.txt”??蛻魴C(jī)和服務(wù)器的命令格式約定為“命令字$路徑名/文件名”,即test.txt文件下載命令格式為“命令字$路徑名/文件名”。圖ChpNum-3 程序流程圖ChpNum-3(a)示出了客戶機(jī)的主程序流程,初始化Winsock后,用socket函數(shù)新建一個(gè)so
13、cket,填寫入服務(wù)器的及IP地址及監(jiān)聽端口后,利用connnect函數(shù)連接到服務(wù)器后即提示用戶輸入ftp命令,程序阻塞在scanf函數(shù)。用戶輸入命令后,scanf函數(shù)返回,通過字符串比對函數(shù)strncmp識別命令,并調(diào)用相應(yīng)的命令發(fā)送函數(shù),若輸入的是quit命令,客戶端程序退出。命令處理函數(shù)主要工作有兩個(gè),一是構(gòu)建命令字節(jié)流發(fā)送到服務(wù)器,二是與服務(wù)器交互該命令的后續(xù)執(zhí)行數(shù)據(jù),例如,對于get命令,該函數(shù)在發(fā)出get命令請求字節(jié)流后,要接收服務(wù)器下發(fā)的文件數(shù)據(jù)。各命令處理函數(shù)的實(shí)現(xiàn)請參見源代碼。圖ChpNum-3(b)示出了服務(wù)器端主程序流程,先初始化Winsock,建立Socket并綁定到監(jiān)
14、聽端口,啟動(dòng)監(jiān)聽,阻塞在Accept函數(shù)等待連接請求的到來,當(dāng)連接請求到達(dá),Accept函數(shù)為該請求創(chuàng)建新的Socket用于與對應(yīng)的客戶通信,而原來Socket繼續(xù)處于監(jiān)聽狀態(tài)。此后,主程序從新的Socket中讀取命令,通過字串比較識別命令,若發(fā)現(xiàn)是quit命令,則關(guān)閉當(dāng)前連接,準(zhǔn)備接收下一個(gè)連接;若不是quit命令,則轉(zhuǎn)移到相應(yīng)的命令處理函數(shù),處理完畢后繼續(xù)在該Socket上讀取命令并進(jìn)行處理。各命令處理函數(shù)的設(shè)計(jì)請參看源代碼。5程序代碼5.1 服務(wù)器端程序文件/*文件名: server.c說明: 簡單的ftp服務(wù)器端程序文件,包含main函數(shù)及get、put等命令處理函數(shù)。*/#inclu
15、de <stdio.h>#include <winsock2.h>#include <stdlib.h>#pragma comment(lib,"ws2_32.lib")WSADATA wsd;char SendBuffer80,RecvBuffer80;/發(fā)送緩沖區(qū)及接收緩沖區(qū)#define DEFAULT_LSTN_PORT 2416 /本地默認(rèn)監(jiān)聽端口int n,bytes;SOCKET h_NewSocket; /accept函數(shù)產(chǎn)生的新socketstruct sockaddr_in RemoteAddr; char path8
16、0=""char strObject100=""int iSynError=1; int sdirfun(SOCKET h_NewSocket);int sgetfun(SOCKET h_NewSocket);int sputfun(SOCKET h_NewSocket);int spwdfun(SOCKET h_NewSocket);int scdfun(SOCKET h_NewSocket);int smdfun(SOCKET h_NewSocket);int sdelfun(SOCKET h_NewSocket);/*函數(shù)名:main說明: 主函數(shù)
17、輸入?yún)?shù): int argc 輸入?yún)?shù)長度 char *argv輸入?yún)?shù),用于傳入監(jiān)聽端口號*/int main(int argc, char *argv) struct sockaddr_in SLocalAddr; SOCKET h_Socket4Lstn; /欲用作監(jiān)聽的socket int addr_in_len;/地址長度 /初始化winsock if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) WSACleanup(); printf("WSAStartup failedn"); memset(&SLocalAd
18、dr,0,sizeof(SLocalAddr); /創(chuàng)建socket h_Socket4Lstn = socket(PF_INET, SOCK_STREAM, 0); if (h_Socket4Lstn <0) printf("creating socket failedn"); SLocalAddr.sin_family = AF_INET; if(argc = 2) SLocalAddr.sin_port = htons(u_short)atoi(argv1); else SLocalAddr.sin_port = htons(DEFAULT_LSTN_PORT)
19、; SLocalAddr.sin_addr.s_addr = INADDR_ANY; /綁定socket if (bind(h_Socket4Lstn,(struct sockaddr *)(&SLocalAddr),sizeof(SLocalAddr) < 0) printf("Bind failed!n"); while (1) /主循環(huán) listen(h_Socket4Lstn,3); /啟動(dòng)監(jiān)聽 addr_in_len = sizeof(RemoteAddr); /接受連接請求 h_NewSocket = accept( h_Socket4Lstn,
20、(struct sockaddr *) (&RemoteAddr) , &addr_in_len); if (h_NewSocket = INVALID_SOCKET) break;/出錯(cuò)退出 printf("%s is connected at port %d n",inet_ntoa(RemoteAddr.sin_addr), ntohs(SLocalAddr.sin_port); sprintf(SendBuffer,"200 Welcome rn"); /向客戶端發(fā)送歡迎消息 bytes = send(h_NewSocket, S
21、endBuffer, strlen(SendBuffer), 0); sprintf(SendBuffer,"530 Log in rn"); bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); while (1) /接收客戶端的命令并調(diào)用命令處理函數(shù) n = 0; iSynError=1; while (1) bytes = recv(h_NewSocket, &RecvBuffern, 1, 0); if (bytes < 0) | (bytes = 0) break; if (Rec
22、vBuffern = '$') RecvBuffern = '0' break; if (RecvBuffern != 'r') n+; if (bytes < 0) | (bytes = 0) break; printf("The Server received: '%s' cmd from client n", RecvBuffer); /命令識別 /查看當(dāng)前目錄 if(strncmp(RecvBuffer,"dir",3)=0) sdirfun(h_NewSocket); /查詢
23、當(dāng)前目錄路徑 if(strncmp(RecvBuffer,"pwd",3)=0) spwdfun(h_NewSocket); /改變當(dāng)前目錄 if (strncmp(RecvBuffer,"cd",2)=0) scdfun(h_NewSocket); /文件下載 if (strncmp(RecvBuffer,"get",3)=0) sgetfun(h_NewSocket); /文件上傳 if (strncmp(RecvBuffer,"put",3)=0) sputfun(h_NewSocket); /新建文件夾 i
24、f (strncmp(RecvBuffer,"md",2)=0) smdfun(h_NewSocket); /刪除文件 if (strncmp(RecvBuffer,"del",3)=0) sdelfun(h_NewSocket); if (strncmp(RecvBuffer,"quit",4)=0) /退出命令 printf("quit n"); sprintf(SendBuffer, "221 Bye bye . rn"); bytes = send(h_NewSocket, SendBu
25、ffer, strlen(SendBuffer), 0); iSynError=0; break; if (iSynError=1) /Syntax error printf("command unrecognized, non-implemented!n"); sprintf(SendBuffer, "500 Syntax error. n"); bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); closesocket(h_NewSocket); printf("%s
26、disconnected from port %d, control socket is closed.n", inet_ntoa(RemoteAddr.sin_addr),ntohs(SLocalAddr.sin_port); closesocket(h_Socket4Lstn); /釋放監(jiān)聽的socket return 0;/*函數(shù)名:sdirfun說明: 用于處理來自客戶端的目錄查詢命令輸入?yún)?shù): SOCKET h_NewSocket,命令通過此socket接收到,可通過它響應(yīng)命令。*/int sdirfun(SOCKET h_NewSocket) char temp_buff
27、er80; FILE *p_FiLeTemp; /整理本地dir命令 strObject0='0' strcat(strObject,"dir "); strcat(strObject,path); strcat(strObject," >tmp.txt"); system(strObject); /system函數(shù)執(zhí)行shell命令 p_FiLeTemp=fopen("tmp.txt","r"); /打開執(zhí)行結(jié)果文件,準(zhǔn)備發(fā)送到客戶端 sprintf(SendBuffer, "12
28、5 Transfering. rn"); bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); while (fgets(temp_buffer,80,p_FiLeTemp)!=NULL) /每次讀取80字節(jié)發(fā)送 sprintf(SendBuffer,"%s",temp_buffer); / send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); fclose(p_FiLeTemp); /發(fā)送完畢,關(guān)閉結(jié)果臨時(shí)文件 sprintf(SendBu
29、ffer, "226 Transfer completed. rn"); bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); system("del tmp.txt"); /刪除結(jié)果臨時(shí)文件 sprintf(SendBuffer,"226 Close the data socket. rn"); bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); printf("dir comman
30、d has been done! n"); iSynError=0; return 0;/*函數(shù)名:sgetfun說明: 用于處理來自客戶端的文件下載命令輸入?yún)?shù): SOCKET h_NewSocket,命令通過此socket接收到,可通過它響應(yīng)命令。*/int sgetfun(SOCKET h_NewSocket) int i=4,k=0; char FileName20,temp_buffer80;char *p_FileName=strObject; FILE *fp;printf("required file is: "); /打印文件名到屏幕while
31、(1) /提取文件名 bytes = recv(h_NewSocket, &RecvBufferi, 1, 0); printf("%c",RecvBufferi); if (bytes < 0) | (bytes = 0) break; FileNamek=RecvBufferi; if (RecvBufferi = '0') FileNamek = '0' break; if (RecvBufferi != 'r') i+; k+; printf("n"); /文件名打印結(jié)束 strObj
32、ect0='0' strcat(strObject,path); if(strlen(path)>0) trcat(strObject,""); strcat(strObject,FileName); /打開客戶端欲下載的文件 if( (fp=fopen(p_FileName,"r") = NULL ) /未成功打開文件 sprintf(SendBuffer, "Sorry, cannot open %s. Please try again.rn", FileName); bytes = send(h_NewSo
33、cket, SendBuffer, strlen(SendBuffer), 0); sprintf(SendBuffer, "226 Transfer completed. rn"); bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); return 1; else printf("The file %s is found,ready to transfer.n",FileName); sprintf(SendBuffer, "125 Transfering. rn&quo
34、t;); bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); while (fgets(temp_buffer,80,fp)!=NULL) /循環(huán)讀取文件并通過h_NewSocket發(fā)送到客戶端 sprintf(SendBuffer,"%s",temp_buffer); send(h_NewSocket, SendBuffer, 80, 0); printf("."); /文件發(fā)送中,每發(fā)80個(gè)字節(jié)在屏幕打一個(gè)點(diǎn)號 fclose(fp); sprintf(SendBuffer, &q
35、uot;226 Transfer completed. rn"); bytes = send(h_NewSocket, SendBuffer, strlen(SendBuffer), 0); iSynError=0; printf("get command has been done! n"); return 0;/*函數(shù)名:sputfun說明: 用于處理來自客戶端的文件上傳命令*/int sputfun(SOCKET h_NewSocket) Printf(“篇幅所限,請讀者完成。n”); iSynError=0; return 0;/*函數(shù)名:spwdfun說
36、明: 用于處理來自客戶端的當(dāng)前路徑查詢命令*/int spwdfun(SOCKET h_NewSocket) Printf(“篇幅所限,請讀者完成。n”); iSynError=0; return 0;/*函數(shù)名:scdfun說明: 用于處理來自客戶端的當(dāng)前路徑設(shè)置命令*/int scdfun(SOCKET h_NewSocket) Printf(“篇幅所限,請讀者完成。n”); iSynError=0; return 0;/*函數(shù)名:smdfun說明: 用于處理來自客戶端的當(dāng)前文件夾新建命令*/int smdfun(SOCKET h_NewSocket) Printf(“篇幅所限,請讀者完成
37、。n”); iSynError=0; return 0;/*函數(shù)名:sdelfun說明: 用于處理來自客戶端的文件刪除命令*/int sdelfun(SOCKET h_NewSocket) Printf(“篇幅所限,請讀者完成。n”); iSynError=0; return 0;5.2 客戶端程序文件/*文件名: client.c說明: 簡單的ftp客戶端程序文件,包含main函數(shù)及get、put等命令發(fā)送函數(shù)。*/#include <winsock2.h>#include <stdio.h>#include <stdlib.h>#pragma comme
38、nt(lib,"ws2_32.lib")#define DEFAULT_SERV_PORT 2416 /服務(wù)器的監(jiān)聽端口#define DEFAULT_BUFFER_SIZE 2048 /緩沖區(qū)長度char sz_ServIp128; / 服務(wù)器的IP地址char sz_Msg2Snd1024; / 發(fā)給服務(wù)器端的字符串int iPort = DEFAULT_SERV_PORT; / 服務(wù)器的監(jiān)聽端口BOOL b_IsSendOnly = FALSE; / 只發(fā)消息,不收消息int dirfun(SOCKET ); /"dir"命令處理函數(shù)int get
39、fun(SOCKET h_Socket4Cmd,char FileName40); /"get"命令處理函數(shù)int putfun(SOCKET h_Socket4Cmd,char FileName40); /"put"命令處理函數(shù)int pwdfun(SOCKET); /"pwd"命令處理函數(shù)int cdfun(SOCKET h_Socket4Cmd,char pathname40); /"cd"命令處理函數(shù)int mdfun(SOCKET h_Socket4Cmd,char DocName20); /"
40、md"命令處理函數(shù)int delfun(SOCKET h_Socket4Cmd,char name20); /"del"命令處理函數(shù)int helpfun(); /"help"命令處理函數(shù)/*函數(shù)名:main說明: 主函數(shù)輸入?yún)?shù): int argc 輸入?yún)?shù)長度 char *argv輸入?yún)?shù)字符型數(shù)組*/int main(int argc, char *argv) WSADATA wsd; SOCKET h_Socket4Cmd; char szBufferDEFAULT_BUFFER_SIZE; int ret; struct sockad
41、dr_in server; struct hostent *host = NULL; char CmdWords5,CmdWords240; argv1="-s:" strcpy(sz_ServIp, &argv13); if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) /winsock初始化 printf("Failed to load Winsock library!n"); return 1; h_Socket4Cmd = socket(AF_INET, SOCK_STREAM,
42、IPPROTO_TCP); if (h_Socket4Cmd = INVALID_SOCKET) printf("creating socket failed, error_code : %dn", WSAGetLastError(); return 1; server.sin_family = AF_INET; server.sin_port = htons(iPort); server.sin_addr.s_addr = inet_addr(sz_ServIp); if (server.sin_addr.s_addr = INADDR_NONE) host = geth
43、ostbyname(sz_ServIp); if (host = NULL) printf("Unable to resolve server: %sn", sz_ServIp); return 1; CopyMemory(&server.sin_addr, host->h_addr_list0, host->h_length); if (connect(h_Socket4Cmd, (struct sockaddr *)&server, sizeof(server) = SOCKET_ERROR) /鏈接到服務(wù)器端 printf("co
44、nnecting to server failed,error_num: %dn", WSAGetLastError(); return 1; /接收服務(wù)器歡迎消息并打印到屏幕 ret = recv(h_Socket4Cmd, szBuffer, DEFAULT_BUFFER_SIZE, 0); if (ret = 0) return 0; else if (ret = SOCKET_ERROR) printf("recv function failed,error_num: %dn", WSAGetLastError(); return 0; szBufferr
45、et = '0' printf("%sn",szBuffer); if(ret<15) ret = recv(h_Socket4Cmd, szBuffer, DEFAULT_BUFFER_SIZE, 0); if (ret = 0) return 0; else if (ret = SOCKET_ERROR) return 0; szBufferret = '0' printf("%sn",szBuffer); helpfun(); /打印命令列表 while(1) puts("-"); prin
46、tf("ftp> "); scanf("%s", CmdWords); /輸入命令掃描 /輸入命令識別 if(strncmp(CmdWords,"dir",3)=0|strncmp(CmdWords,"DIR",3)=0) dirfun(h_Socket4Cmd); continue; else if(strncmp(CmdWords,"pwd",3)=0|strncmp(CmdWords,"PWD",3)=0) pwdfun(h_Socket4Cmd); continue; else if(strncmp(CmdWords,"?"
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 加工承攬意向合同范本
- 出讓合同范本
- 買磚合同范本
- 兒女撫養(yǎng)合同范本
- 農(nóng)村租房建基站合同范本
- 代建合同范本政府蓋章
- 世界500強(qiáng)合同范本
- 會(huì)務(wù)代辦合同范本
- 供貨定金合同范本
- 別墅門窗出售合同范本
- 七年級下冊《平行線的判定》課件與練習(xí)
- 2025年中考英語時(shí)文閱讀 6篇有關(guān)電影哪吒2和 DeepSeek的英語閱讀(含答案)
- 修高速土方合同范例
- 2024年湖北省武漢市中考語文試卷
- 二零二五年度高品質(zhì)小區(qū)瀝青路面翻新施工與道路綠化合同2篇
- 2024年形勢與政策復(fù)習(xí)題庫含答案(綜合題)
- 工程項(xiàng)目部安全生產(chǎn)治本攻堅(jiān)三年行動(dòng)實(shí)施方案
- 2024三農(nóng)新政策解讀
- HGE系列電梯安裝調(diào)試手冊(ELS05系統(tǒng)SW00004269,A.4 )
- 酒店前臺績效考核表
- 水利工程水庫混凝土防滲墻施工方案
評論
0/150
提交評論