SMTP 프로토콜 (Simple Mail Transfer Protocol)
1) 메일을 송신한다.

2) 수신자는 본인의 컴퓨터가 켜져있지 않기 때문에 수신할 머신이 필요하다.

3) Mail Server 는 수신자를 대신해서 메일을 수신하고 이후 사용자가 보길 원하는 경우, 사용자에게 보여준다.


Mail Server에는 Mail Queue가 존재하는데, 수신자 쪽 서버가 멈추거나 다운된 경우 송신자쪽 서버의 큐에 담아두고 이후에 안정화가 되면 보낸다.


Http : 클라이언트가 서버로부터 데이터를 가져오는 모습

Smtp : 보내고자 하는 데이터를 밀어넣는 형태


Http 는 사용자가 데이터를 끌어오는 방식 (pull)

Smtp 는 사용자가 데이터를 밀어내는 방식 (push)


Http 는 메세지가 두 개가 존재하였다. request & response

Smtp 는 메세지가 여러 개로 분해되어 존재한다. (HELO, MAIL FROM, RCPT TO, DATA ...)


Gmail Server 와 Naver Server 간의 메일 송수신은 smtp로 하지만 클라이언트가 해당 메일을 가져오는 프로토콜은 http 로 한다.


What is a Socket

네트워크란, 프로세스간의 메세지를 교환하는 것이며, 서로 다른 머신 간에 통신을 위한 것이다. 프로세스들간의 커뮤니케이션을 위한 OS에서 제공하는 인터페이스를 이용한다.


해당하는 인터페이스가 바로 Socket 이다. 소켓을 통한 두 가지 방식이 존재한다.


순서

(1) TCP Server 에서 socket() 을 생성하고 bind() 한다. (특정한 포트번호에 매핑) 해당 소켓의 포트번호를 설정하는 것.

(2) 이후 listen()을 수행하여 소켓은 대기하며 accept() 를 통해 외부로부터의 요청을 기다린다.

(3) TCP Client 측에서 socket()을 생성하고 connect() 를 통해서 TCP Server와 연결한다. 이 과정에서 TCP - Three-way handshaking 이 일어난다.

(4) 이후에는 write() 와 read() 가 일어난다.

  • 소켓 API 익히기.

  • Http Request Message & Http Response Message 익히기.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package http_server;
 
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class HttpdConnection {
    private static ServerSocket serverSocket;
 
    public static void main(String[]args) throws IOException{
        // 스레드 풀 이용 최대 3개
        Executor executor = Executors.newFixedThreadPool(3);
        serverSocket = new ServerSocket(Integer.parseInt(args[0]));
        
        // 계속 기다림. 
        // 클라이언트의 요청 최대 3개까지 (스레드 풀 영향)
        while(true){
            Socket socket = serverSocket.accept();
            DoubleRHttpdConnection doubleRHttpdConnection = new DoubleRHttpdConnection(socket);    
            
            executor.execute(doubleRHttpdConnection);
        }
        
    }
}
 
class DoubleRHttpdConnection implements Runnable{
    
    Socket clientSocket;
    
    public DoubleRHttpdConnection(Socket clientSocket){
        this.clientSocket = clientSocket;
    }
    
    @Override
    public void run() {
        try{
            // 소켓 읽기
            InputStream in = clientSocket.getInputStream();
            InputStreamReader isr = new InputStreamReader(in"8859_1");
            BufferedReader br = new BufferedReader(isr);
            
            // 소켓 쓰기
            OutputStream out = clientSocket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out"8859_1");
            PrintWriter pw = new PrintWriter(osw, true);
            
            String request = br.readLine();
            System.out.println("Request : " + request);
            
            Matcher get = Pattern.compile("GET /?(\\S*).*").matcher(request);
            
            if( get.matches() ){
                request = get.group(1);
                
                if(request.endsWith("/"|| request.equals(""))
                    request = request + ".index.html";
                
                try{
                    FileInputStream fis = new FileInputStream(request);
                    byte[]data = new byte[64 * 1024];
                    
                    for(int read; (read = fis.read(data)) > -1;)
                        out.write(data, 0, read);
                    
                    out.flush();
                }
                catch(FileNotFoundException e){
                    pw.println("404 Object Not Found");
                }
            }
            else
            pw.println("400 Bad Request");
            
            clientSocket.close();
        }
        catch(IOException e){
            System.out.println("I/O error " + e.getMessage());
        }
    }
}
 
cs



정리 )

  • SMTP 프로토콜 개념
  • Mail Queue 는 무엇인가
  • HTTP Protocol 과 SMTP Protocol 이 데이터를 송수신하는 모습 (push 와 pull 로 설명)
  • Socket 은 무엇인가


Posted by doubler
,