검색결과 리스트
2011/03/09에 해당되는 글 3건
- 2011.03.09 리눅스 파일시스템 계층 표준(Filesystem Hierarchy Standard)
- 2011.03.09 [FTP] (2) 클라이언트 구현하기
- 2011.03.09 [FTP] (1) FTP(File Transmission Protocol) 프로토콜 이해
글
리눅스 파일시스템 계층 표준(Filesystem Hierarchy Standard)
다음은 Filesystem Hierarchy Standard 2.3 내용을 간략히 요약한 내용이다.
Bin
시스템 관리자와 사용자가 동시에 사용하는 명령을 포함하고 있으며, 이 명령들은 다른 파일시스템이 마운팅 될 필요가 없는 명령이다. (싱글 유저 모드)
스크립트에서 간접적으로 사용되는 명령들도 포함하고 있다. /bin 디렉토리에는 서브디렉토리가 없어여 한다.
다음은 bin 디렉토리에서 볼 수 있는 몇 가지 명령들이다.
cat, chmod, chirp, cp, date, echo, kill, mv, ls
/boot (부트로더의 정적파일)
이 디렉토리는 부팅시 필요한 초기화 파일을 포함하여 부팅과정에서 필요한 모든 것을 포함하고 있다.
커널이 유저모드 프로그램 실행을 시작 시키기 전에 사용되는 데이터를 저장하고 있다. . 저장된 마스터 부트 섹터와 섹터 맵파일을 포함하고 있다
운영체제 커널은 / (루트) 또는 /boot 디렉토리에 위치해야한다.
이 디렉토리는 부팅시 필요한 초기화 파일을 포함하여 부팅과정에서 필요한 모든 것을 포함하고 있다.
커널이 유저모드 프로그램 실행을 시작 시키기 전에 사용되는 데이터를 저장하고 있다. . 저장된 마스터 부트 섹터와 섹터 맵파일을 포함하고 있다
운영체제 커널은 / (루트) 또는 /boot 디렉토리에 위치해야한다.
/dev (디바이스 파일)
디바이스 파일들이 있는 디렉토리이다. /dev 에 디바이스들이 수동으로 생성될 필요가 있다면 , MAKEDEV 라는 이름의
명령을 포함해야한다.
로컬 디바이스를 위해 MAKEDEV.local 을 포함할수도 있다.
/etc (호스트에 있는 특정시스템에 대한 구성파일)
configuration file을 포함한다. 구성파일이란 프로그램에 동작방식을 제어하는 로컬파일을 의미한다. 정적파일이어야 하며, 실행가능한 바이너리여서는 안된다
서브디렉토리 opt는 :/opt에 대한 설정을, X11 는 X Window 시스템에 대한 설정을, sgml 은 SGML 에 대한 설정을, xml은 XML에 대한 설정파일을 포함한다.
configuration file을 포함한다. 구성파일이란 프로그램에 동작방식을 제어하는 로컬파일을 의미한다. 정적파일이어야 하며, 실행가능한 바이너리여서는 안된다
서브디렉토리 opt는 :/opt에 대한 설정을, X11 는 X Window 시스템에 대한 설정을, sgml 은 SGML 에 대한 설정을, xml은 XML에 대한 설정파일을 포함한다.
/home(사용자 홈디레토리)
사이트에 대한 파일시스템으로, 호스트 마다 설정이 다를 수 있기 때문에 프로그램들은 이 위치에 의존해서는 안된다.
사용자 개인의 애플리케이션 설정파일은 .(dot)으로 시작하는 이름으로 홈디렉토리에 저장된다. 애플리케이션이 dot 파일을 하나이상 생성해야한다면 dot 디렉토리를
생성하고, 거기에 .dot으로 시작하지 않는 이름으로 설정파일들을 저장해야한다.
사이트에 대한 파일시스템으로, 호스트 마다 설정이 다를 수 있기 때문에 프로그램들은 이 위치에 의존해서는 안된다.
사용자 개인의 애플리케이션 설정파일은 .(dot)으로 시작하는 이름으로 홈디렉토리에 저장된다. 애플리케이션이 dot 파일을 하나이상 생성해야한다면 dot 디렉토리를
생성하고, 거기에 .dot으로 시작하지 않는 이름으로 설정파일들을 저장해야한다.
/lib (필수적인 공유 라이브러리와 커널 모듈)
시스템을 부팅시키거나 루트 파일시스템에서 명령을 실행하는데 필요한 공유라이브러리 이미지가 존재한다.
예를 들어 /bin이나 /sbin에서…필요한…
다음과 같은 이름패턴을 가지고 있어야한다.
libc.so.* 는 동적으로 링크된 c 라이브러리이며, ld* 는 실행타임 링커/로더를 나타낸다.
시스템을 부팅시키거나 루트 파일시스템에서 명령을 실행하는데 필요한 공유라이브러리 이미지가 존재한다.
예를 들어 /bin이나 /sbin에서…필요한…
다음과 같은 이름패턴을 가지고 있어야한다.
libc.so.* 는 동적으로 링크된 c 라이브러리이며, ld* 는 실행타임 링커/로더를 나타낸다.
/media (제거가능한 미디어에 다한 마운트 위치)
플로피 디스크나 cdrom, zip 디스크와 같은 제거 가능한 미디어를 위한 마운트 포인트로 사용되는 서브디렉토리를 포함한다
/mnt (일시적으로 마운트되는 파일시스템을 위한 마운트포인트)
/opt (애드온 애플리케이션 소프트웨어 패키지)
애드온 애플리케이션 소프트웨어 패키지 설치를 위해 제공되는 디렉토리이다. . /opt에 설치된 패키지는 /opt/<package>, /opt/<provider> 에서 정적파일을 찾을수 있어야한다 <package> 는 소프트웨어 패키지를 기술하는 이름이며, <provider> 는
제공자의 LANANA 등록된 이름이다.
애드온 애플리케이션 소프트웨어 패키지 설치를 위해 제공되는 디렉토리이다. . /opt에 설치된 패키지는 /opt/<package>, /opt/<provider> 에서 정적파일을 찾을수 있어야한다 <package> 는 소프트웨어 패키지를 기술하는 이름이며, <provider> 는
제공자의 LANANA 등록된 이름이다.
/root (루트유저 홈데릭토리)
/sbin (시스템 바이너리)
/tmp (임시파일)
'운영체제로그 > Linux' 카테고리의 다른 글
| Wget (0) | 2011.04.25 |
|---|---|
| 리눅스 자격증 (0) | 2011.04.09 |
| 리눅스 파일시스템 계층 표준(Filesystem Hierarchy Standard) (0) | 2011.03.09 |
| su, sudo : 특정 사용자 권한으로 쉘/명령 실행 (0) | 2011.03.08 |
| cURL (0) | 2011.02.18 |
| grub에서 디폴트 부팅 os 변경하기 (0) | 2011.02.16 |
설정
트랙백
댓글
글
[FTP] (2) 클라이언트 구현하기
다음은 c언어로 구현한 open, get, put, ls, cd, pwd, quit/bye, hash 명령을 구현한 간단한 FTP 클라이언트 예제이다. 에러처리와 소켓의 recv, send 함수의 동작방식을 정확히 고려하지 않았기 때문에, 정확히 동작하지 않을 수 있다. 데이터 수신시 하나의 명령에 대한 메시지의 끝을 구분해 줄 수 있는 방법이 추가로 필요하다. (메시지 끝을 의미하는 \r\n 로 구분) : Ftp 커맨드 및 상수를 정의한 헤더파일
#define CMD_OPEN "open"
#define CMD_LIST "ls"
#define CMD_GET "get"
#define CMD_PUT "put"
#define CMD_PWD "pwd"
#define CMD_CD "cd"
#define CMD_QUIT "quit"
#define CMD_BYE "bye"
#define CMD_HASH "hash"
#define CMD_SHELL "!"
#define MODE_DEBUG 1
#define MODE_NORMAL 0
#define FTP_PORT 21
extern int mode;
void debug(char *msg) {
if (mode == MODE_DEBUG) {
printf("[debug] : %s \n", msg);
}
}
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define TEMP_BUFFER_SIZE 1024
int connectServer(char *serverIp, short port) {
int sock;
struct sockaddr_in servAddr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("sock failed");
exit(1);
}
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(serverIp);
servAddr.sin_port = htons(port);
if (connect(sock, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) {
perror("connect failed");
exit(1);
}
return sock;
}
void sendProtocol(int sock, char *protocol) {
if (send(sock, protocol, strlen(protocol), 0) != strlen(protocol)) {
perror("send failed");
exit(1);
}
if (MODE_DEBUG == mode) {
printf("send: %s", protocol);
}
}
void recvProtocol(int sock, char *recvBuffer, int bufferSize) {
int recvLen;
if ((recvLen = recv(sock, recvBuffer, bufferSize-1, 0)) <= 0) {
perror("recv failed");
exit(1);
}
recvBuffer[recvLen] = '\0';
if (MODE_DEBUG == mode) {
printf("recv: %s", recvBuffer);
}
}
unsigned int downloadFile(int sock, char *filePath, unsigned int fileSize, int hashFlag) {
char readBuffer[TEMP_BUFFER_SIZE];
unsigned int readBytes, totalBytes, numHash;
int fd = open(filePath, O_WRONLY | O_CREAT, 0744);
totalBytes = numHash = 0;
while (totalBytes < fileSize) {
if ((readBytes = read(sock, readBuffer, TEMP_BUFFER_SIZE)) <= 0) {
close(fd);
return totalBytes;
}
write(fd, readBuffer, readBytes);
totalBytes += readBytes;
if (hashFlag) {
if ((totalBytes/TEMP_BUFFER_SIZE) > numHash) {
numHash++;
printf("#");
}
}
}
close(fd);
printf("\n");
return totalBytes;
}
unsigned int uploadFile(int sock, char *filePath, int hashFlag) {
char readBuffer[TEMP_BUFFER_SIZE];
unsigned int readBytes, totalBytes, numHash;
int fd = open(filePath, O_RDONLY);
totalBytes = numHash = 0;
while ((readBytes = read(fd, readBuffer, TEMP_BUFFER_SIZE)) > 0) {
write(sock, readBuffer, readBytes);
totalBytes += readBytes;
if (hashFlag) {
if ((totalBytes/TEMP_BUFFER_SIZE) > numHash) {
numHash++;
printf("#");
}
}
}
close(fd);
printf("\n");
return totalBytes;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "FtpCommand.h"
#include "ClientSocket.h"
#define COMMAND_MAX_SIZE 1024
#define BUFFER_SIZE 1024
#define FILENAME_SIZE 256
#define END_OF_PROTOCOL "\r\n"
void initializeFtpClient();
void startFtpClient(char *ip, char *port);
void commandHandle(char *cmd);
void defaultHandler(char *cmd);
int modeCheck(const char *option);
void printMessage(char *msg);
void openCon(char *cmd);
void list(char *listCmd);
void get(char *getCmd);
void put(char *putCmd);
void cd(char *cdCmd);
void quit(char *quitCmd);
void pwd(char *pwdCmd);
void bye(char *byeCmd);
void hash(char *hashCmd);
void passiveMode(char *ip, int *port);
void shellEscape(char *shellCmd);
unsigned int downloadFile(int sock, char *filePath, unsigned int fileSize, int hashFlag);
unsigned int uploadFile(int sock, char *filePath, int hashFlag);
typedef struct _FtpCmdHandler {
char cmd[5];
void (*handler)(char* arg);
} FtpCmdHandler;
// Map Ftp Command to Handler
FtpCmdHandler ftpCmdHandler[] = {
{ CMD_OPEN, openCon },
{ CMD_LIST, list },
{ CMD_PUT, put },
{ CMD_GET, get },
{ CMD_CD, cd },
{ CMD_PWD, pwd },
{ CMD_HASH, hash },
{ CMD_QUIT, quit },
{ CMD_BYE, bye },
{ CMD_SHELL, shellEscape },
};
// sock - PI socket , dtpSock - DTP socket
int sock, dtpSock;
int state;
int mode;
int hashFlag;
int main (int argc, char const *argv[])
{
if (argc == 3) {
// argv[1] == ip, argv[2] == port
startFtpClient(argv[1], argv[2]);
} else if (argc == 4 && modeCheck(argv[1]) == MODE_DEBUG) {
// argv[1] == -d, argv[2] = ip, argv[3] == port
startFtpClient(argv[2], argv[3]);
} else {
fprintf(stderr, "Usage: %s [-d] \n", argv[0]);
}
return 0;
}
int modeCheck(const char *option) {
if (!strcmp(option, "-d")) {
// debug mode
mode = MODE_DEBUG;
} else {
mode = MODE_NORMAL;
}
return mode;
}
// initialize ftp client
void initializeFtpClient() {
hashFlag = 1;
state = INITIAL_STATE;
debug("initialized");
}
// ftp client start
void startFtpClient(char *ip, char *port) {
char cmd[COMMAND_MAX_SIZE];
initializeFtpClient();
while (1) {
// input user command
if (ip == 0 && port == 0) {
printMessage("ftp>");
fgets(cmd, COMMAND_MAX_SIZE, stdin);
} else {
sprintf(cmd, "open %s %s", ip, port);
startCmd = 0;
}
// call handler
commandHandle(cmd);
}
}
// map command to handler
void commandHandle(char *cmd) {
int i;
int numCmd = sizeof(ftpCmdHandler)/sizeof(FtpCmdHandler);
for (i = 0; i < numCmd; i++) {
if (!strncmp(cmd, ftpCmdHandler[i].cmd, strlen(ftpCmdHandler[i].cmd))) {
(*(ftpCmdHandler[i].handler))(cmd);
break;
}
}
}
void defaultHandler(char *cmd) {
printf("default handler: %s\n", cmd);
}
// ftp server connect
void openCon(char *openCmd) {
char serverIp[16], serverPort[16];
char cmd[BUFFER_SIZE];
char sendBuffer[BUFFER_SIZE];
char recvBuffer[BUFFER_SIZE];
sscanf(openCmd,"%*s %s %s%*c", serverIp, serverPort);
debug(serverIp);
// connect to server
sock = connectServer(serverIp, atoi(serverPort));
recvProtocol(sock, recvBuffer, BUFFER_SIZE-1);
// send user name
printf("Name: ");
fgets(cmd, COMMAND_MAX_SIZE, stdin);
sprintf(sendBuffer, "User %s", cmd);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE-1);
printMessage(recvBuffer);
// send password
printf("Password: ");
fgets(cmd, COMMAND_MAX_SIZE, stdin);
sprintf(sendBuffer, "PASS %s", cmd);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE-1);
printMessage(recvBuffer);
// get server os information
sprintf(sendBuffer, "SYST%s", END_OF_PROTOCOL);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE-1);
printMessage(recvBuffer);
}
// send EPSV or PASS to Server
void passiveMode(char *ip, int *port) {
char sendBuffer[BUFFER_SIZE];
char recvBuffer[BUFFER_SIZE];
int host0, host1, host2, host3;
int port0, port1;
sprintf(sendBuffer, "PASV%s", END_OF_PROTOCOL);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE-1);
printMessage(recvBuffer);
sscanf(strchr(recvBuffer, '(')+1, "%d,%d,%d,%d,%d,%d", &host0, &host1, &host2, &host3, &port0, &port1);
sprintf(ip, "%d.%d.%d.%d", host0, host1, host2, host3);
*port = port0*256 + port1;
debug(ip);
printf("dtp port : %d\n", *port);
}
// get remote working directory file list
void list(char *listCmd) {
int port;
char ip[16];
char sendBuffer[BUFFER_SIZE];
char recvBuffer[BUFFER_SIZE*8];
debug("list");
// recv server response and parsing
passiveMode(ip, &port);
// connect to DTP
dtpSock = connectServer(ip, port);
// send LIST command to PI server
sprintf(sendBuffer, "LIST%s", END_OF_PROTOCOL);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
// recv file list from DTP
recvProtocol(dtpSock, recvBuffer, BUFFER_SIZE*8);
printMessage(recvBuffer);
// recv complete message from PI server
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
close(dtpSock);
}
// file download
void get(char *getCmd) {
int port;
unsigned int fileSize;
char ip[16], filePath[FILENAME_SIZE], fileName[50];
char sendBuffer[BUFFER_SIZE];
char recvBuffer[BUFFER_SIZE];
// get local current working directory
getcwd(filePath, FILENAME_SIZE);
sscanf(getCmd, "%*s %s%*c", fileName);
sprintf(filePath, "%s/%s", filePath, fileName);
debug("get");
printf("fileName: %s\n", fileName);
printf("filePath: %s\n", filePath);
passiveMode(ip, &port);
// connect to DTP
dtpSock = connectServer(ip, port);
// request server for transfer start - RETR fileName
sprintf(sendBuffer, "RETR %s%s", fileName, END_OF_PROTOCOL);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
// extract fileSize
sscanf(strchr(recvBuffer, '(')+1, "%u", &fileSize);
printf("fileSize: %u\n", fileSize);
// download file from DTP
downloadFile(dtpSock, filePath, fileSize, hashFlag);
// recv complete message from PI server
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
close(dtpSock);
}
// file upload
void put(char *putCmd) {
int port;
unsigned int fileSize;
char ip[16], filePath[FILENAME_SIZE], fileName[50];
char sendBuffer[BUFFER_SIZE];
char recvBuffer[BUFFER_SIZE];
sscanf(putCmd, "%*s %s%*c", fileName);
// get local current working directory
getcwd(filePath, FILENAME_SIZE);
sscanf(putCmd, "%*s %s%*c", fileName);
sprintf(filePath, "%s/%s", filePath, fileName);
debug("put");
debug(filePath);
passiveMode(ip, &port);
// connect to DTP
dtpSock = connectServer(ip, port);
// request server for transfer start - STOR fileName
sprintf(sendBuffer, "STOR %s%s", fileName, END_OF_PROTOCOL);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
// file upload to DTP
fileSize = uploadFile(dtpSock, filePath, hashFlag);
close(dtpSock);
/// recv complete message from PI server
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
}
// change remote working directory
void cd(char *cdCmd) {
char sendBuffer[BUFFER_SIZE];
char recvBuffer[BUFFER_SIZE];
debug("cd");
sscanf(cdCmd, "%*s %s%*c", recvBuffer);
debug(recvBuffer);
sprintf(sendBuffer, "CWD %s%s", recvBuffer, END_OF_PROTOCOL);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
}
// ftp client exit
void quit(char *quitCmd) {
char sendBuffer[BUFFER_SIZE];
char recvBuffer[BUFFER_SIZE];
debug("quit");
sprintf(sendBuffer, "QUIT%s", END_OF_PROTOCOL);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
close(sock);
exit(0);
}
// same quit
void bye(char *byeCmd) {
quit(0);
}
// get remote working directory
void pwd(char *pwdCmd) {
char sendBuffer[BUFFER_SIZE];
char recvBuffer[BUFFER_SIZE];
debug("pwd");
sprintf(sendBuffer, "PWD%s", END_OF_PROTOCOL);
sendProtocol(sock, sendBuffer);
recvProtocol(sock, recvBuffer, BUFFER_SIZE);
printMessage(recvBuffer);
}
// hash option on/off
void hash(char *hashCmd) {
debug("hash");
hashFlag = !hashFlag;
if (hashFlag == 0) {
printMessage("hash off");
} else {
printMessage("hash on");
}
}
// shell command - not implemented
void shellEscape(char *shellCmd) {
printMessage("not implemented");
}
void printMessage(char *msg) {
printf("%s", msg);
}
'네트워크로그' 카테고리의 다른 글
| [FTP] (2) 클라이언트 구현하기 (0) | 2011.03.09 |
|---|---|
| [FTP] (1) FTP(File Transmission Protocol) 프로토콜 이해 (0) | 2011.03.09 |
| 바이트 오더링(byte ordering) (0) | 2011.03.08 |
| OAuth의 세부사항 (0) | 2011.01.01 |
| OAuth의 개념과 대략적인 흐름 (0) | 2010.12.31 |
설정
트랙백
댓글
글
[FTP] (1) FTP(File Transmission Protocol) 프로토콜 이해
1. FTP 란?
FTP 는 2대의 컴퓨터 간에 파일 전송을 위한 애플리케이션 프로토콜로 RFC 959에 정의되어 있다.
Transport 계층 프로토콜로 TCP를 사용하며, 클라이언트/서버 모델 구성을 가지고 있으며, FTP 서버는
21번 포트에서 FTP 클라이언트의 접속을 기다린다. FTP는 텔넷과는 달리, 클라이언트와 서버간에 2개의
커넥션을 맺어 통신을 한다. 제어 명령을 송수신하는 PI(Protocol Interpreter) 프로세스와, 데이터를 송수신하는
DTP(Data Transmission Process) 로 구성된다.
2. Active 모드 vs Passive 모드
데이터를 전송하는 방식에 따라 Active 모드와 Passive 모드가 존재한다. 서버를 기준으로 했을 때, 서버가
클라이언트에 접속하여 데이터를 송수신하는 것을 Active 모드라 하며, 클라이언트가 서버에 접속하여
데이터를 송수신하는 것이 Passive 모드이다.
3. FTP 애플리케이션의 구조
FTP 애플리케이션의 구조는 다음과 같다.
알툴즈의 알 FTP 와 같이 그래픽 유저 인터페이스를 제공하는 FTP 클라이언트도 있는가 하면, 유닉스/리눅스에서와 같이
터미널에서 동작하는 텍스트 인터페이스의 FTP 클라이트도 존재한다. 하지만 어떤 클라이언트 형태는 RFC959에 정의된
FTP 프로토콜에 따라 내부적으로 FTP 서버와 통신하게 된다.
FTP 클라이언트 인테페이스를 통해, FTP 명령을 치면 클라이언 PI와 서버 PI간에 통신이 이루어진다. 작업디렉토리에 파일목록
출력과 데이터 업로드, 다운로드와 같은 작업들은 PI 를 통해 초기화가 이루어지면, 실제 데이터 전송은 서버와 클라이언트의 DTP
간에 별도의 커넥션을 통해 이루어진다.
PI와 DTP는 구조상에 개념이며, 반드시 FTP 클라이어트가 2개의 프로세스로 구성되어야 하는 것은 아니다.
한 개의 프로세스여도, 프로토콜 전송 주소와 포트, 절차만을 준수하면 이상없이 서버와 통신할 수 있다.
4. FTP 명령 / 명령을 완료하기 위해 전송되는 프로토콜
FTP 클라이언트에서 사용할 수 있는 명령들은 다음과 같다. 더 많지만 자주 사용되는 명령들만을 간추려 보았다.
| 커맨드 | 기능 | 프로토콜 |
|---|---|---|
| open <아이피 주소 또는 호스트명> |
해당 주소의 FTP 서버로 접속한다. 접속이 성공하면 Name과 Password를 입력하여 로그인할 수 있다. |
커넥트 USER PASS SYST |
| pwd | 현재 원격(서버) 작업 디렉토리를 얻어온다. | PWD |
| cd <디렉토리> | 원격 작업 디렉토리를 변경한다 | CWD |
| ls | 현재 원격 작업디렉토리의 파일목록을 얻어온다. |
PASV LIST |
| hash | 파일 업로드/다운로드시 1024바이트 단위로 해시문자 출력 옵셥을 on/off 한다. | |
| get <파일명> | 서버에 파일을 로컬로 다운로드한다. |
PASV GET |
| put <파일명> | 로컬 파일으로 서버로 업로드한다. |
PASV PUT |
| quit/bye | FTP를 종료한다. | QUIT |
| !<쉘명령> | 셀 이스케이프. 쉘 명령을 수행하고, FTP 로 되돌아온다. | |
| ascii / binary | 파일을 아스키 또는 바이너리로 전송한다. | TYPE I./A |
| ? | FTP 명령 사용법을 출력한다. |
커맨드는 텍스트 기반 FTP 클라이언트에서 사용자게 터미널을 통해 입력받는 명령이며, 이러한 명령의 기능을 수행하기 위해
클라이언트는 서버에게 한개 이상의 프로토콜을 전송하게 된다. 클라이언트가 서버에게 전송하는 프로토콜은 텍스트이며,
프토토콜의 종결문자로 \r\n을 사용한다. 다음은 몇가지 FTP 프로토콜이다.
4.1 FTP 프로토콜
| 커맨드 | 내용 | 비고 |
|---|---|---|
| USER 사용자명 | FTP 계정에 사용자 명을 전송한다 | |
| PASS 비밀번호 | FTP 계정에 사용자 비밀번호를 전송한다 | |
| SYST | FTP 서버에 운영체제 종류를 문의한다. | |
| PWD | 현재 작업디렉토리 경로를 얻어온다. | |
| CWD 디렉토리 | 인자로 주어진 디렉토리로 현재 작업디렉토리를 변경한다 | |
| PASV | passive 모드로 전환한다. 서버는 클라이언트의 접속을 기다릴 주소와 포트를 쉼표를 구분자로 하여 (127,0,0,1,234,13) 의 포맷으로 응답해준다. | |
| LIST | 현재 작업 디렉토리의 파일목록을 얻어온다. | |
| GET 파일명 | 원격 작업디렉토리 상에 파일을 로컬로 다운로드 한다. | |
| PUT 파일명 | 로컬의 파일을 원격 작업디렉토리로 업로드 한다. | |
| RETR | 로컬로 파일 다운로드시 클라이언트가 서버에게 데이터 전송시작을 요청한다. | |
| STOR | 파일 업로드시 클라이언트가 서버에게 데이터 전송시작을 요청한다. | |
| PORT h0,h1,h2,h3,p0,p1 | Active 모드로 데이터 전송시 서버에게 클라이언트가 대기할 주소와 포트를 쉼표를 구분자로 전송한다. p0, p1은 2바이트 포트의 각 바이트의 십진수값이다 | |
| QUIT | 연결을 종료한다. |
4.2 데이터 전송모드
데이터 전송은 passive 모드와 active 모드로 전송할 수 있으며, 그 개념상에 차이는 이전에 설명했다. active 모드로 데이터
전송시 클라이언트는 PORT 명령을 통해 서버가 접속할 수 있도록 클라이언트가 대기할 주소와 포트번호를 전송한다.
앞에 2개의 수는 IP 를 구성하고 있는 수들이며, 4, 103은 2바이트 포트번호의 각 바이트를 십진수로 표현한 값(4x256 + 103)이다.
즉 위 프로토콜을 해석하면 202.13.180.230 주소, 1127 포트에서 대기할 테니 여기로 서버는 접속하시오 ~~ 라는 의미가
되겠다. 이렇게 서버가 클라이언트에게 접속하면, 클라이언트는 바로 데이터를 전송하면 된다.
passive 모드에서는 클라이언트는 PASV 프르토콜을 전송하여 passive 모드로 데이터를 전송받겠다는 것을 서버에게 알리면,
서버는 위와 통일한 포맷으로 서버가 대기할 주소와 포트번호를 알려준다. 클라이언트는 이 값을 읽어들여 해당 주소로 접속한다.
이후 LIST, RETR, STOR 을 전송하여 실제 데이터 전송을 시작해달라고 요청하게 된다.
다음은 이를 나타내고 있는 그림이다.
'네트워크로그' 카테고리의 다른 글
| [FTP] (2) 클라이언트 구현하기 (0) | 2011.03.09 |
|---|---|
| [FTP] (1) FTP(File Transmission Protocol) 프로토콜 이해 (0) | 2011.03.09 |
| 바이트 오더링(byte ordering) (0) | 2011.03.08 |
| OAuth의 세부사항 (0) | 2011.01.01 |
| OAuth의 개념과 대략적인 흐름 (0) | 2010.12.31 |
FtpCommand.h