-
10.2.4.3 예 3: 네트워크 애플리케이션 계층 프로토콜 개발
Tsinghua University Press "Java Programmers, Things to Do at Work" 저자: Zhong Sheng - 10장 "마스터는 능력만큼 재능이 있습니다"에서 일부 발췌.
누구나 FTP 업로드 및 다운로드 도구를 사용해 본 적이 있을 것입니다. 예를 들어, "LeapFTP"는 그림에 표시된 것처럼 매우 편리한 FTP 서버 업로드 및 다운로드 도구입니다. 이 도구는 매우 편리합니다. 사용자 이름과 비밀번호를 입력하면 FTP 서버에서 파일 목록을 볼 수 있어 업로드 및 다운로드 작업이 간편해집니다.
Java로 FTP 파일 업로드 및 다운로드 애플리케이션을 작성해 본 적이 있습니까?
Java도 이러한 프로그램을 개발할 수 있습니다. 먼저 Java의 FTP 툴킷을 사용하여 FTP 애플리케이션을 개발하는 방법을 살펴보겠습니다.
sun.net.* 가져오기;
import sun.net.ftp.*;
공개 클래스 FTP {
공개 정적 무효 메인(String[] args) {
String server="192.168.0.12"; //FTP 서버의 IP 주소를 입력하세요.
String user="useway"; //FTP 서버에 로그인하기 위한 사용자 이름
String Password=" !@#$%abce "; //FTP 서버에 로그인하기 위한 사용자 이름의 비밀번호
String path="/home/useway"; //FTP 서버의 경로
노력하다 {
FtpClient ftpClient=new FtpClient() //FtpClient 개체 생성
ftpClient.openServer(server); //FTP 서버에 연결
ftpClient.login(user, 비밀번호); //FTP 서버에 로그인합니다.
if (path.length()!=0) ftpClient.cd(경로);
TelnetInputStream은=ftpClient.list();
정수 c;
while ((c=is.read())!=-1) {
System.out.print((char)c);
}
is.close();
ftpClient.closeServer();//FTP 서버 종료
}
catch(예외예외){
}
}
}
관심이 있다면 이 프로그램을 직접 작성할 수 있습니다. 이 프로그램이 실행되면 그림과 같은 상황이 나타나며 서버측 프로그램의 디렉터리 내용이 나열됩니다.
이 프로그램은 FTP 서버의 파일 목록을 가져오는 간단한 프로그램이지만 오해하지 마십시오. 이 프로그램은 "Network Application Layer Protocol" 프로그램의 개발이라고 할 수 없습니다!
이 프로그램은 FTP 측을 작동하기 위해 "sun.net.*;" 및 "sun.net.ftp.*"의 관련 클래스만 사용합니다. 요청은 클라이언트로 전송되지만 링크 요청은 Java에서 제공하는 툴킷을 통해 서버로 전송됩니다.
FTP 서버에 연결하기 위해 Java의 FTP 패키지를 사용하는 이점은 네트워크 수준에서 데이터를 보내는 구체적인 세부 사항에 신경 쓸 필요가 없고 해당 메서드만 호출하면 된다는 것입니다. FTP 서버에 연결하기 위해 Java의 FTP 패키지를 사용할 때의 단점은 개발자가 애플리케이션 계층 프로토콜 송수신의 내용을 모르고 원칙을 이해할 수 없으며 기본 데이터에 대한 이해가 매우 약하다는 것입니다.
이 시점에서 일부 프로그래머는 "FTP는 네트워크 수준에서 PC와 서버 간에 어떻게 상호 작용합니까?"라고 묻습니다. FTP 프로토콜 상호 작용 프로세스를 나열하겠습니다.
FTP 프로토콜 상호 작용에 대한 다음 예를 살펴보십시오.
FTP 서버: 220(vsFTPd 2.0.1)
FTP 클라이언트: USER 사용 방법
FTP 서버: 331 비밀번호를 지정하세요.
FTP 클라이언트: PASS !@#$%abce
FTP 서버: 230 로그인에 성공했습니다.
FTP 클라이언트: CWD /home/useway
FTP 서버: 250 디렉터리가 성공적으로 변경되었습니다.
FTP 클라이언트: EPSV ALL
FTP 서버: 200 EPSV 모두 괜찮습니다.
FTP 클라이언트: EPSV
FTP 서버: 229 확장 수동 모드 시작(|||62501|)
FTP 클라이언트: 목록
FTP 서버: 150 여기에 디렉토리 목록이 표시됩니다.
FTP 서버: 226 디렉토리 전송이 정상입니다.
FTP 클라이언트: 종료
FTP 서버: 221 안녕하세요.
위 텍스트는 실제로 FTP 서버와 FTP 클라이언트 사이의 상호 작용 과정이며, 이들 사이에서 정보를 전송하는 프로토콜은 TCP 프로토콜이고, 서로 전송되는 내용은 위 텍스트에 적힌 내용입니다.
각 문장의 의미를 단계별로 설명해 보겠습니다.
FTP 서버: 220(vsFTPd 2.0.1) 설명: 연결 성공 |
FTP 클라이언트: USER useway |지침: 사용자 이름을 입력하세요.
FTP 서버: 331 비밀번호를 지정하세요. |설명: 비밀번호를 입력하세요.
FTP 클라이언트: PASS !@#$%abce |지침: 비밀번호를 입력하세요
FTP 서버: 230 로그인 성공. 설명: 로그인에 성공했습니다.
FTP 클라이언트: CWD /home/useway 설명: 디렉토리 전환 |
FTP 서버: 250 디렉토리가 성공적으로 변경되었습니다. |설명: 디렉토리 전환이 성공했습니다.
FTP 클라이언트: EPSV ALL 설명: EPSV 패시브 링크 모드
FTP 서버: 200 EPSV 모두 괜찮습니다.
FTP 클라이언트: EPSV 설명: 링크 |
FTP 서버: 229 확장 수동 모드 시작(|||62501|) |설명: 수동 링크 포트는 62501입니다.
FTP 클라이언트: LIST 설명: LIST를 실행하여 파일 목록을 표시합니다.
FTP 서버: 150 다음은 디렉터리 목록입니다. 설명: 목록은 포트 62501에서 전송됩니다.
FTP 서버: 226 디렉토리 전송이 완료되었습니다. |설명: 전송이 완료되었습니다.
FTP 클라이언트: QUIT 설명: FTP 종료 |
FTP 서버: 221 안녕히 계세요. 설명: 안녕히 계세요.
위 텍스트의 내용을 사용하면 도구 없이도 FTP 파일 목록을 얻을 수 있습니다. 믿을 수 없다면 저를 따라 다시 해보세요.
1단계: 먼저 CMD를 열어 DOS 명령줄 모드로 들어가서 다음을 입력합니다.
텔넷 192.168.0.1 21[Enter]
설명: Ftp 서버의 포트 21에 대한 Telnet입니다.
이 명령을 실행한 후 얻은 결과는 그림과 같습니다.
문제를 발견하셨나요?
프롬프트의 내용은 정확히 위 단락의 첫 번째 문장인 220(vsFTPd 2.0.1)입니다. 이는 FTP 서버가 링크를 수락했으며 다음 단계로 진행할 수 있음을 의미합니다.
2단계: 다음과 같은 일련의 전송 내용을 하나씩 입력합니다.
USER 사용방법[Enter]
PASS !@#$%abce [Enter]
CWD /집/사용 방법[Enter]
EPSV 전체[Enter]
EPSV[Enter]
얻은 결과가 그림에 나와 있습니다.
자, 이번에는 FTP 서버가 일련의 응답을 주었고 마침내 새로운 포트 번호 "58143"을 제공했습니다.
3단계: 새 CMD 창을 열고 다음을 입력합니다.
텔넷 192.168.0.1 58143[Enter]
참고로 이번에 서버에 접속하기 위한 Telnet 요청의 포트번호는 "58143"인데, 이는 FTP 서버에서 우리에게 제공하는 링크 포트입니다. 연결한 후에는 그림과 같이 아무 메시지도 없이 창이 비어 있습니다.
4단계: 첫 번째 CMD 창으로 돌아가서 다음을 입력합니다.
목록[Enter]
5단계: 이때 두 번째 CMD 창은 파일 목록을 수신합니다.
두 번째 창은 그림과 같이 파일 목록을 수신합니다.
6단계: 작업 종료
종료[Enter]
실행이 완료되면 그림과 같이 호스트에 대한 링크가 끊어집니다.
보시다시피 FTP 프로토콜은 시스템과 함께 제공되는 Telnet 도구를 사용하여 FTP의 이러한 기본 명령 작업을 완료할 수도 있습니다. 위 작업을 완료하기 위해 Java 소켓을 사용하려면 위 내용을 단계별로 따라 문자열을 FTP 서버로 보내면 됩니다.
아래에 예제 코드도 제공됩니다.
import java.io.InputStream;
import java.io.OutputStream;
java.net.Socket 가져오기;
공개 클래스 FTPClient{
public static void main(String[] args)에서 예외 발생{
소켓 소켓 = new Socket("192.168.0.1",21);
InputStream은 = 소켓.getInputStream();
OutputStream os = 소켓.getOutputStream();
//초기 링크 정보 수신
바이트[] 버퍼 = 새 바이트[100];
int 길이 = is.read(버퍼);
String s = new String(버퍼, 0, 길이);
System.out.println(s);
//사용자 이름 보내기
String str = "USER 사용 방법n";
os.write(str.getBytes());
//반환값을 받아온다
길이 = is.read(버퍼);
s = 새로운 문자열(버퍼, 0, 길이);
System.out.println(s);
//비밀번호 보내기
str = "통과 !@#$%abcdn ";
os.write(str.getBytes());
//반환값을 받아온다
길이 = is.read(버퍼);
s = 새로운 문자열(버퍼, 0, 길이);
System.out.println(s);
//폴더 전환 명령 보내기
str = "CWD /home/usewayn";
os.write(str.getBytes());
//반환값을 받아온다
길이 = is.read(버퍼);
s = 새로운 문자열(버퍼, 0, 길이);
System.out.println(s);
//모드 설정
str = "EPSV 모두n";
os.write(str.getBytes());
//반환값을 받아온다
길이 = is.read(버퍼);
s = 새로운 문자열(버퍼, 0, 길이);
System.out.println(s);
//패시브 모니터링 정보 가져오기
str = "EPSVn";
os.write(str.getBytes());
//반환값을 받아온다
길이 = is.read(버퍼);
s = 새로운 문자열(버퍼, 0, 길이);
System.out.println(s);
//FTP 패시브 모니터링을 위한 포트 번호를 가져옵니다.
String portlist=s.substring(s.indexOf("(|||")+4,s.indexOf("|)"));
System.out.println(portlist);
//ShowList 스레드 클래스를 인스턴스화하고 FTP 수동 수신 포트 번호를 연결합니다.
ShowList sl=new ShowList();
sl.port=Integer.parseInt(portlist);
sl.start();
//LIST 명령 실행
str = "목록n";
os.write(str.getBytes());
//반환값을 받아온다
길이 = is.read(버퍼);
s = 새로운 문자열(버퍼, 0, 길이);
System.out.println(s);
//링크 닫기
is.close();
os.close();
소켓.닫기();
}
}
//패시브 링크 정보 클래스를 가져옵니다. 이 클래스는 다중 스레드입니다.
클래스 ShowList는 Thread를 확장합니다.
공개 int 포트=0;
공개 무효 실행(){
노력하다{
소켓 소켓 = new Socket("192.168.0.1",this.port);
InputStream은 = 소켓.getInputStream();
OutputStream os = 소켓.getOutputStream();
바이트[] 버퍼 = 새 바이트[10000];
int 길이 = is.read(버퍼);
String s = new String(버퍼, 0, 길이);
System.out.println(s);
//링크 닫기
is.close();
os.close();
소켓.닫기();
}
catch(예외예외){
}
}
}
프로그램을 실행한 후 얻은 실행 결과는 기본적으로 위의 실행 효과와 동일합니다.우리가 이해하는 한 캡슐화된 메서드를 풀고 실행하는 것 이상은 아닙니다. 작동 규칙에 따라 동일한 프로그램을 개발할 수 있습니다.