c++实现ftp服务器_第三步,尝试用树莓派搭建你的云计算平台和服务器
學完前兩步,最后讓我們用網頁調用你剛剛設計好的內容,進行擴展部分云計算平臺的搭建!簡單的來說分為以下幾點:
1,通過網頁訪問rcS文件設置開發板IP,避免重啟后服務器IP訪問失效。然后通過TCP傳輸協議實現文件的傳輸。
2,實現嵌入式云計算平臺的搭建,可試樹莓派、arm開發板等。
3,將復雜運算集中在服務器端,客戶端作為接收數據的載體,將數據發送到服務器完成運算后只需要接受結果即可,大大降低了客戶端的計算壓力。
4,實例演示的一個簡單的四則運算,加減乘除,向服務器發送add 4 5,即可返回the result is 9。
”移植web_server
開發板中移植web服務器,我選擇的是Boa,因為Boa是一種非常小巧的Web服務器,其可執行代碼只有大約60KB左右。作為一種單任務Web服務器,Boa只能依次完成用戶的請求,而不會fork出新的進程來處理并發連接請求。但Boa支持CGI,能夠為CGI程序fork出一個進程來執行。Boa的設計目標是速度和安全。
Boa移植的過程較簡單,文章里就不一一描述了,詳細過程可以點擊“閱讀原文”查看,但提醒大家在移植的過程中注意修改文src/compat.h、src/log.c、src/boa.c,否則會出現一堆錯誤。
網絡訪問頁面配置通過移植Boa后,我們就可以手動把網頁文件index.html拷入到/www目錄下,在瀏覽器輸入IP地址即可看到對應網頁。但重啟開發板之后,需要重新配置IP才可訪問網頁。如果我們想要重新通過固定IP訪問網頁,接下來就需要配置IP,netmask,gateway。
在瀏覽器看到對應三個輸入框,輸入對應IP,Netmask,Gateway之后,發送到對應的cgi程序處理,后面會對cgi具體內容做介紹。
rcS文件配置:
rcS文件是開發板啟動后自動執行的腳本文件,用戶可以在里面添加自定義的一些配置。
這里我通過cgi程序修改rcS文件,而rcS文件里面保存由網絡頁面輸入的IP,netmask,gateway配置。
ifconfig eth0 192.168.100.102 netmask 255.255.255.0route?add?default?gw?192.168.100.101cgi程序設計:
用c語言設計了一個cgi程序,接收網頁發來的數據,并完成對應的操作。
(加部分程序,在程序里查看原文)
printf("%s%c%c\n",?"Content‐Type:text/html;charset=iso‐8859‐1",?13,10);printf("IP Configuration\n");printf("IP Configuration
\n");data = getenv("QUERY_STRING");if(data == NULL)printf("ERROR:no input setup or transmission meet with troubles!"
);else?if(sscanf(data,?"address=%[0‐9,.]&netmask=%[0‐9,.]&gateway=%[0‐9,.]",?address,?netmask,?gateway)!=3)printf("ERROR:input is invalid!"
);else{printf("%s%c%c\n",?"Content‐Type:text/plain;charset=iso‐8859‐1",13,10);strcat(strcat(strcat(strcat(strcpy(line0, str0), address), str1), netmask), tab);//?原文里包含所有代碼前面塊中數據發送的方式是"GET",這里我們通過:getenv("QUERY_STRING")來去接受數據并放在地址data上。通過sscanf函數完成數據的分配。之后打開文件,寫入對應行,即可完成IP配置的操作。在sscanf函數里面,可能會注意到%[0-9,.]這種不同于傳統%s,%d的數據模式。這是因為特殊字符會經過URL編碼,會帶來數據接受的錯誤,而上述模式可以解決這個問題。
頁面設置文件傳輸功能
在開發板移植了FTP程序,然后在主機安裝vsftpd程序,在主機打開vcstpd程序,然后在通過頁面選擇開發板上輸入主機的IP地址,是上傳還是下載文件,輸入文件的名字即可通過TCP協議完成文件的傳輸。
首先,網絡頁面配置
<form action="/cgi‐bin/ftp.cgi" method="GET" target="nm_iframe"><p>please?input?address,?transmission?type,?file?pathp><label>IP?Address:<input?name="address"?size="30"?maxlength="40">label><br><label>Transmission?Type:<input?type="radio"?name="trans_type"?value="download">Downloa<br><input?type="radio"?name="trans_type"?value="upload">Uploadlabel><br><label>File?Path:<input?name="file_path">label><br><input?type="SUBMIT"?value="Send">form>其次,在開發板上安裝ftp
使用busybox制作的根文件系統,沒有ftp客戶端工具,無法登錄到其他的ftp服務器,需要自己編譯ftp指令。ftp客戶端我選擇的是netkitftp0.17.tar.gz。(安裝過程見“閱讀原文”)
再次,在主機上安裝vsftpd
安裝并啟動vsftpd:
sudo apt‐get install vsftpdservice vsftpd start最后,shell腳本編寫
FTP傳輸需要通過網頁完成,所以我寫了兩個shell腳本文件(ftp_upload.sh, ftp_download.sh),由網頁讀取目標主機IP地址,然后根據傳輸需要,通過cgi程序讀取文件名稱執行不同的傳輸操作。
ftp_upload.sh:
#!/bin/shftp?‐v?‐n?$1<user?edision?soc20174?binarycd /home/edision/Downloadlcd uftppromptput $2byeEOFecho?"commit?to?ftp?successfully"$1參數為目標主機的IP地址,$2為上傳文件名
ftp_download.sh:
#!/bin/shftp?‐v?‐n?$1<user?edision?soc2017binarycd?/home/edision/Downloadlcd?uftppromptget?$2byeEOFecho?"download?from?ftp?successfully"$1參數為目標主機的IP地址,$2為下載文件名
通過cgi程序接收到IP地址和文件名后,根據傳輸類型的不同,選擇對應的腳本文件,然后執行。這里我的文件傳輸通過多線程是支持多用戶連接的,可以極大提高傳輸效率。然后定義了一個URL譯碼程序,在用戶傳輸特殊字符(這里主要是路徑斜線),可以將傳輸的URL碼轉譯為對應的特殊符號。
云計算demo
socket服務器端與客戶端通信過程
從圖中可以看出,當客戶端調用connect時,觸發了連接請求,向服務器發送了SYN J包,這時connect進入阻塞狀態;
服務器監聽到連接請求,即收到SYN J包,調用accept函數接收請求向客戶端發送SYN K ,ACK J+1,這時accept進入阻塞狀態;
客戶端收到服務器的SYN K ,ACKJ+1之后,這時connect返回,并對SYN K進行確認;
服務器收到ACK K+1時,accept返回,至此三次握手完畢,連接建立。
socket中TCP的握手釋放連接
某個應用進程首先調用close主動關閉連接,這時TCP發送一個FIN M;
另一端接收到FIN M之后,執行被動關閉,對這個FIN進行確認。它的接收也作為文件結束符傳遞給應用進程,因為FIN的接收意味著應用進程在相應的連接上再也接收不到額外數據;
一段時間之后,接收到文件結束符的應用進程調用close關閉它的socket。這導致它的TCP也發送一個FIN N;
接收到這個FIN的源發送端TCP對它進行確認。
服務器程序設計:
本次設計的程序需要支持多用戶連接,因此我設計了多線程連接的思想,來為每一個客戶的訪問申請一個子線程。
所以首先定義了sgi_handler函數用于獲取子進程退出信號,在退出時給出提示信息。然后在用戶輸入add/sub/mul/div op1 op2來去執行運算以獲得返回結果。程序主體:
1. 首先定義了一個結構體,存儲操作符和數據。
2. 子進程退出提示信號函數。
3. 創建socket()描述符用于標示唯一的socket,然后賦予其協議域,socke類型以及指定協議。
4. bind()函數把ipv4地址和端口號賦予socket。
5. listen()函數監聽這個socket,如果客戶端調用connect()發出連接請求,服務器就可以接收到這個請求。
6. TCP服務器端監聽到這個請求之后,就會調用accept()函數取接收請求,這樣連接就建立好了。
7. 之后通過fork()函數創建子進程,通過read函數讀取內容進行處理,并通過write函數將結果寫回到客戶端,并等待下一條命令的輸入。
客戶端程序設計
發送add/sub/mul/div op1 op2指令到服務器端,獲得返回的結果。結構相對服務器端不用考慮多線程的問題,結構較為簡單。
1. 首先定義了一個結構體,存儲操作符和數據。
2. 創建socket()描述符用于標示唯一的socket,然后賦予其協議域,socke類型以及指定協議。
3. bind()函數把ipv4地址和端口號賦予socket。
4. listen()函數監聽這個socket,如果客戶端調用connect()發出連接請求,服務器就可以接收到這個請求。
5. 客戶端向服務端發送連接請求
6. 連接成功之后向服務器發送命令并等待返回結果。
兩個程序設計的源碼,可以點擊“閱讀原文”下載。
成果運行示例:
服務器端:
總結
這次實驗首先是服務器的移植,讓我了解了網頁的制作。然后明白瀏覽器是怎么通過IP地址來去訪問服務器,真是深感神奇。
第一次做出來了自己期望的網頁界面(雖然很簡陋),從網頁的學習我現在有明白了之前爬蟲爬下來網頁的內容的含義,對我以后制作自動下載的腳本幫助甚大。
第二個是要在頁面能夠配置IP。我思索了整整兩天,最開始是希望通過能夠在網頁上書寫javascript來去修改本地的rcS文件,但是這個想法真的是純屬異想天開,最終選擇放棄。后來經過仔細調研最終選擇了通過cgi程序來去和瀏覽器完成數據的交互,這給我開啟了一個新世界的大門,如果可以這樣的話,我可以通過網頁發送期望的數據來完成和開發板的交互。
第三個通過TCP協議完成文件的傳輸。原本我想的是在開發板上配置vsftpd,然后通過遠程ftp訪問,但是發現面臨無法調用用戶端的腳本文件的問題,因此轉換了一下思路,在目標主機上安裝vsftpd,在開發板上運行ftp,這種思維轉為又給我帶來了新的靈感。然后shell腳本也會編寫了,嵌入式真是一門綜合性的學科。
最后socket編程的學習讓我了解了服務器和用戶是怎么完成網絡通信的。
以上三篇便是我在設計嵌入式開發板云計算平臺的搭建過程中分享的全部內容,流程及重點要關注的地方也給大家提示了,希望大家都可以輕松的搭建自己的云計算平臺!
如果在開發中遇到問題,我在達爾聞技術交流群里等著你!
總結
以上是生活随笔為你收集整理的c++实现ftp服务器_第三步,尝试用树莓派搭建你的云计算平台和服务器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: textarea 聚焦后边框_texta
- 下一篇: mysql左连接_MySQL left