1. 程式人生 > >使用 Socket 通訊實現 FTP 客戶端程式

使用 Socket 通訊實現 FTP 客戶端程式

簡介: FTP 客戶端如 FlashFXP,File Zilla 被廣泛應用,原理上都是用底層的 Socket 來實現。FTP 客戶端與伺服器端進行資料交換必須建立兩個套接字,一個作為命令通道,一個作為資料通道。前者用於客戶端向伺服器傳送命令,如登入,刪除某個檔案,後者用於接收資料,例如下載或上傳檔案等。本文詳細闡述如何呼叫系統介面傳送 FTP 命令實現檔案上傳下載等 FTP 客戶端功能,讓讀者對 FTP 客戶端的原理有一個深入的瞭解。

FTP 概述

檔案傳輸協議(FTP)作為網路共享檔案的傳輸協議,在網路應用軟體中具有廣泛的應用。FTP的目標是提高檔案的共享性和可靠高效地傳送資料。

在傳輸檔案時,FTP 客戶端程式先與伺服器建立連線,然後向伺服器傳送命令。伺服器收到命令後給予響應,並執行命令。FTP 協議與作業系統無關,任何作業系統上的程式只要符合 FTP 協議,就可以相互傳輸資料。本文主要基於 LINUX 平臺,對 FTP 客戶端的實現原理進行詳盡的解釋並闡述如何使用 C 語言編寫一個簡單的 FTP 客戶端。

FTP 協議

相比其他協議,如 HTTP 協議,FTP 協議要複雜一些。與一般的 C/S 應用不同點在於一般的C/S 應用程式一般只會建立一個 Socket 連線,這個連線同時處理伺服器端和客戶端的連線命令和資料傳輸。而FTP協議中將命令與資料分開傳送的方法提高了效率。

FTP 使用 2 個埠,一個數據埠和一個命令埠(也叫做控制埠)。這兩個埠一般是21 (命令埠)和 20 (資料埠)。控制 Socket 用來傳送命令,資料 Socket 是用於傳送資料。每一個 FTP 命令傳送之後,FTP 伺服器都會返回一個字串,其中包括一個響應程式碼和一些說明資訊。其中的返回碼主要是用於判斷命令是否被成功執行了。

命令埠

一般來說,客戶端有一個 Socket 用來連線 FTP 伺服器的相關埠,它負責 FTP 命令的傳送和接收返回的響應資訊。一些操作如“登入”、“改變目錄”、“刪除檔案”,依靠這個連線傳送命令就可完成。

資料埠

對於有資料傳輸的操作,主要是顯示目錄列表,上傳、下載檔案,我們需要依靠另一個 Socket來完成。

如果使用被動模式,通常伺服器端會返回一個埠號。客戶端需要用另開一個 Socket 來連線這個埠,然後我們可根據操作來發送命令,資料會通過新開的一個埠傳輸。

如果使用主動模式,通常客戶端會發送一個埠號給伺服器端,並在這個埠監聽。伺服器需要連線到客戶端開啟的這個資料埠,並進行資料的傳輸。

主動模式下,客戶端隨機開啟一個大於 1024 的埠向伺服器的命令埠 P,即 21 埠,發起連線,同時開放N +1 埠監聽,並向伺服器發出 “port N+1” 命令,由伺服器從它自己的資料埠 (20) 主動連線到客戶端指定的資料埠 (N+1)。

FTP 的客戶端只是告訴伺服器自己的埠號,讓伺服器來連線客戶端指定的埠。對於客戶端的防火牆來說,這是從外部到內部的連線,可能會被阻塞。

為了解決伺服器發起到客戶的連線問題,有了另一種 FTP 連線方式,即被動方式。命令連線和資料連線都由客戶端發起,這樣就解決了從伺服器到客戶端的資料埠的連線被防火牆過濾的問題。

被動模式下,當開啟一個 FTP 連線時,客戶端開啟兩個任意的本地埠 (N > 1024 和 N+1) 。

第一個埠連線伺服器的 21 埠,提交 PASV 命令。然後,伺服器會開啟一個任意的埠 (P > 1024 ),返回如“227 entering passive mode (127,0,0,1,4,18)”。 它返回了 227 開頭的資訊,在括號中有以逗號隔開的六個數字,前四個指伺服器的地址,最後兩個,將倒數第二個乘 256 再加上最後一個數字,這就是 FTP 伺服器開放的用來進行資料傳輸的埠。如得到 227 entering passive mode (h1,h2,h3,h4,p1,p2),那麼埠號是 p1*256+p2,ip 地址為h1.h2.h3.h4。這意味著在伺服器上有一個埠被開放。客戶端收到命令取得埠號之後, 會通過 N+1 號埠連線伺服器的埠 P,然後在兩個埠之間進行資料傳輸。

FTP 每個命令都有 3 到 4 個字母組成,命令後面跟引數,用空格分開。每個命令都以 "\r\n"結束。

要下載或上傳一個檔案,首先要登入 FTP 伺服器,然後傳送命令,最後退出。這個過程中,主要用到的命令有 USER、PASS、SIZE、REST、CWD、RETR、PASV、PORT、QUIT。

USER: 指定使用者名稱。通常是控制連線後第一個發出的命令。“USER gaoleyi\r\n”: 使用者名稱為gaoleyi 登入。

PASS: 指定使用者密碼。該命令緊跟 USER 命令後。“PASS gaoleyi\r\n”:密碼為 gaoleyi。

SIZE: 從伺服器上返回指定檔案的大小。“SIZE file.txt\r\n”:如果 file.txt 檔案存在,則返回該檔案的大小。

CWD: 改變工作目錄。如:“CWD dirname\r\n”。

PASV: 讓伺服器在資料埠監聽,進入被動模式。如:“PASV\r\n”。

PORT: 告訴 FTP 伺服器客戶端監聽的埠號,讓 FTP 伺服器採用主動模式連線客戶端。如:“PORT h1,h2,h3,h4,p1,p2”。

RETR: 下載檔案。“RETR file.txt \r\n”:下載檔案 file.txt。

STOR: 上傳檔案。“STOR file.txt\r\n”:上傳檔案 file.txt。

REST: 該命令並不傳送檔案,而是略過指定點後的資料。此命令後應該跟其它要求檔案傳輸的 FTP 命令。“REST 100\r\n”:重新指定檔案傳送的偏移量為 100 位元組。

QUIT: 關閉與伺服器的連線。

客戶端傳送 FTP 命令後,伺服器返回響應碼。

響應碼用三位數字編碼表示:

第一個數字給出了命令狀態的一般性指示,比如響應成功、失敗或不完整。

第二個數字是響應型別的分類,如 2 代表跟連線有關的響應,3 代表使用者認證。

第三個數字提供了更加詳細的資訊。

第一個數字的含義如下:

1 表示伺服器正確接收資訊,還未處理。

2 表示伺服器已經正確處理資訊。

3 表示伺服器正確接收資訊,正在處理。

4 表示資訊暫時錯誤。

5 表示資訊永久錯誤。

第二個數字的含義如下:

0 表示語法。

1 表示系統狀態和資訊。

2 表示連線狀態。

3 表示與使用者認證有關的資訊。

4 表示未定義。

5 表示與檔案系統有關的資訊。

Socket 客戶端程式設計主要步驟如下:

    1、socket() 建立一個 Socket

    2、connect() 與伺服器連線

    3、write() 和 read() 進行會話

    4、close() 關閉 Socket

Socket 伺服器端程式設計主要步驟如下:

  1. socket() 建立一個 Socket
  2. bind()
  3. listen() 監聽
  4. accept() 接收連線的請求
  5. write() 和 read() 進行會話
  6. close() 關閉 Socket

         1、客戶端和 FTP 伺服器建立 Socket 連線。

         2、向伺服器傳送 USER、PASS 命令登入 FTP 伺服器。

        3、使用 PASV 命令得到伺服器監聽的埠號,建立資料連線。

         4、使用 RETR/STOR 命令下載/上傳檔案。

        5、在下載完畢後斷開資料連線併發送 QUIT 命令退出。

當客戶端與伺服器建立連線後,伺服器會返回 220 的響應碼和一些歡迎資訊。

struct hostent *hp;

struct sockaddr_in server;

memset(&server, 0, sizeof(struct sockaddr_in));

control_sock = socket(AF_INET, SOCK_STREAM, 0);

hp = gethostbyname(server_name);

memcpy(&server.sin_addr,

hp->h_addr, hp->h_length);

server.sin_family = AF_INET;

server.sin_port = htons(port);

connect(control_sock,(struct sockaddr *)&server, sizeof(server));

read(control_sock, read_buf, read_len);

當客戶端傳送使用者名稱和密碼,伺服器驗證通過後,會返回 230 的響應碼。然後客戶端就可以向伺服器端傳送命令了。
圖 2. 客戶端登入 FTP 伺服器

sprintf(send_buf,"USER %s\r\n",username);

write(control_sock, send_buf, strlen(send_buf))

;

read(control_sock, read_buf, read_len);

sprintf(send_buf,"PASS %s\r\n",password);

write(control_sock, send_buf, strlen(send_buf));

read(control_sock, read_buf, read_len);

當客戶端在下載/上傳檔案前,要先發送命令讓伺服器進入被動模式。伺服器會開啟資料埠並監聽。並返回響應碼 227 和資料連線的埠號。

sprintf(send_buf,"PASV\r\n");

write(control_sock, send_buf, strlen(send_buf));

read(control_sock, read_buf, read_len);

當客戶端傳送命令下載檔案。伺服器會返回響應碼 150,並向資料連線傳送檔案內容。

當客戶端下載完畢後,傳送命令退出伺服器,並關閉連線。伺服器會返回響應碼 200。

首先,伺服器準備就緒後返回 220。客戶端接收到伺服器端返回的響應碼後,相繼傳送“USER username” 和 “PASS password” 命令登入。隨後,伺服器返回的響應碼為 230 開頭,說明客戶端已經登入了。這時,客戶端傳送 PASV 命令讓伺服器進入被動模式。伺服器返回如 “227 Entering Passive Mode (127,0,0,1,13,67)”,客戶端從中得到埠號,然後連線到伺服器的資料埠。接下來,客戶端傳送下載命令,伺服器會返回響應碼 150,並從資料埠傳送資料。最後,伺服器返回 “226 transfer complete”,表明資料傳輸完成。

需要注意的是,客戶端不要一次傳送多條命令,例如我們要開啟一個目錄並且顯示這個目錄,我們得傳送 CWD dirname,PASV,LIST。在傳送完 CWD dirname 之後等待響應程式碼,然後再發送後面一條。當 PASV 返回之後,我們開啟另一個 Socket 連線到相關埠上。然後傳送 LIST,返回 125 之後在開始接收資料,最後返回 226 表明完成。

在傳輸多個檔案的過程中,需要注意的是每次新的傳輸都必須重新使用 PASV 獲取新的埠號,接收完資料後應該關閉該資料連線,這樣伺服器才會返回一個 2XX 成功的響應。然後客戶端可以繼續下一個檔案的傳輸。

上傳檔案與下載檔案相比,登入驗證和切換被動模式都如出一轍,只需要改變傳送到伺服器端的命令,並通過資料連線傳送檔案內容。

相關推薦

使用 Socket 通訊實現 FTP 客戶程式

簡介: FTP 客戶端如 FlashFXP,File Zilla 被廣泛應用,原理上都是用底層的 Socket 來實現。FTP 客戶端與伺服器端進行資料交換必須建立兩個套接字,一個作為命令通道,一個作為資料通道。前者用於客戶端向伺服器傳送命令,如登入,刪除某個檔案,後者

使用C語言socket實現windows pc與ftp伺服器通訊---socket實現ftp客戶

code // Client.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <iostream> #include <fstream> #include <WinSock2.h&

C# 實現FTP客戶

枚舉 username rect 進行 sco fine pac out puts 本文是利用C# 實現FTP客戶端的小例子,主要實現上傳,下載,刪除等功能,以供學習分享使用。 思路: 通過讀取FTP站點的目錄信息,列出對應的文件及文件夾。 雙擊目錄,則顯示子目錄,如果是

ftp客戶程式的三個實驗

準備好兩臺互相ping通的虛擬機器 一。匿名使用者 安裝需要用的包 vim 編輯主配置檔案 vim /etc/vsftpd/vsftpd.conf 第十二行等於YES 第十五行等於NO 27行和31行的#去掉 重啟服務service vsftpd restart 到客戶機端 安裝ftp服

最簡單的socket通訊伺服器和客戶

底部附上了效果圖 伺服器程式碼: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java

java網路程式設計:8、基於TCP的socket程式設計(一)簡單的socket通訊_一個客戶

宣告:本教程不收取任何費用,歡迎轉載,尊重作者勞動成果,不得用於商業用途,侵權必究!!! 文章目錄 一、基於tcp的程式設計,就好像用電話進行交談一樣 二、在java中用於程式設計網路程式的類 三、套接字 + (輸出、輸入流) 1、伺服器程式編寫基本步驟: 2、客戶端程式

Socket 通訊原理(Android客戶和伺服器以TCP&&UDP方式互通)

ZERO、前言 有關通訊原理內容是在網上或百科整理得到,程式碼部分為本人所寫,如果不當,還望指教。 一、Socket通訊簡介  Android與伺服器的通訊方式主要有兩種,一是Http通訊,一是Socket通訊。兩者的最大差異在於,http連線使用的是“請求—響應方式

Socket例項1--POP3客戶程式

下面的程式碼例項基於POP3的客戶協議,與郵件伺服器連線並取回指定使用者帳號的郵件。  與郵件伺服器互動的命令存在字串陣列POPMessage中,程式通過一個do-while迴圈依次傳送這些命令。#include<stdio.h> <stdlib.h> <errno.h>

Python 實現FTP客戶:ftplib模組的使用

1. FTP常用方法總結如下: from ftplib import FTP 匯入包 ftp = FTP() 例項化ftp物件 ftp.set_debuglevel(2) 開啟除錯級別2,顯示詳細資訊 ftp.set_debuglevel(0)

用python編寫ftp客戶程式

#!/usr/bin/env python#author:Jims of www.ringkee.com#create date: 2005/02/05#description: Using ftplib module download a file from a ftp server.from ftplib

socket 通訊寫出客戶和伺服器通訊 , 要求客戶傳送資料後能夠回顯相同的資料

比較基礎的一個服務端客戶端互相通訊的程式/** * @author john socket 的伺服器端,接收到資料後列印到控制檯 的資料 * */ public class ServiceSocket_1 { public static void main(

實現socket的服務和客戶通訊

對學習過程中自己敲的一些關於socket有關的程式碼做了個簡單總結,在這分享一下,給有需要的同學借鑑一下。 什麼是socket? 網路上的兩個程式通過一個雙向的通訊連線實現資料的交換,這個連線的一端稱為一個socket。 建立網路通訊連線至少要一對埠號(socket)。socke

Java Socket應用(三)多執行緒實現客戶通訊

伺服器執行緒處理類ServerThread.java : package com.yijia; import java.io.*; import java.net.Socket; /** * 建立時間:2018/10/4 14:59 * 作者: * 郵箱:[ema

Socket通訊實現伺服器和客戶對話

廣域網和區域網 介紹socket通訊前我們先介紹一下廣域網與區域網的概念。區域網簡稱LAN,是指在某一區域幾臺計算機組成的計算機組,區域網是封閉的,區域網經常採用共享通道,即共用同一條電纜。廣域網簡稱WAN,是一種跨越大的,地域性的地區性網路集合廣域網包含大大小

linux網路程式設計之用socket實現簡單客戶和服務通訊(基於TCP)

一、介紹基於TCP協議通過socket實現網路程式設計常用API 1、讀者如果不是很熟悉,可以先看我之前寫的幾篇部落格,有socket,地址結構的理解,更加方便讀者理解 地址分別是: 2、socket(TCP)程式設計API簡介 1)、socket int s

linux網路程式設計之用socket實現簡單客戶和服務通訊(基於UDP)

1、sendto和recvfrom函式介紹 sendto(經socket傳送資料) 相關函式 send , sendmsg,recv , recvfrom , socket 表頭檔案 #include < sys/types.h >#includ

ftp客戶socket實現

#ifndef CLIENT_H_  #define CLIENT_H_    //#include <sys/socket.h>  #include<winsock.h> #include<assert.h> //#include <

android中利用Socket實現手機客戶與PC進行通訊

伺服器端: import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; impor

Socket 服務使用多執行緒實現客戶通訊例項

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; impo

C++ Socket網路通訊實現一個伺服器和多個客戶通訊

一 描述1 採用C++語言 2 編譯環境是code::blocks 3 使用的是非阻塞套接字 二 功能描述1 一個伺服器對多個客戶端 2 伺服器端主要負責處理資料的輸入併發送,具體是通過傳送指令向其指定的客戶端傳送資料,傳送接收指令讀取其指定的客戶端傳送的資料 3 客戶端的