์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[JAVA] 1:1 ์–‘๋ฐฉํ–ฅ ํ†ต์‹ (์ฑ„ํŒ… ๊ธฐ๋ณธ ๊ธฐ๋Šฅ ๊ตฌํ˜„)

JAVA

by ๋ฏธ๋กœ910 2024. 5. 24. 16:07

๋ณธ๋ฌธ

๐Ÿ’ก๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™œ์šฉ
์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์ง€์†์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๋ชจ๋‘์—์„œ ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ๋ฐ›์•„ ์ƒ๋Œ€๋ฐฉ์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์Šค๋ ˆ๋“œ์™€ while ๋ฌธ์„ ํ™œ์šฉํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ด…์‹œ๋‹ค.
์„œ๋ฒ„ ์ธก ์ฝ”๋“œ
โ—ผ ServerSocket ์„ ์ƒ์„ฑํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ์„ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
โ—ผ BufferedReader ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ๊ณ , PrintWriter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
โ—ผ ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด BufferedReader๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
โ—ผ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์Šค๋ ˆ๋“œ์™€ ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋‚ด๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ๊ฐ๊ฐ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class MultiThreadServer {


		// ๋ฉ”์ธ ํ•จ์ˆ˜ 
		public static void main(String[] args) {
			
			System.out.println("===  ์„œ๋ฒ„ ์‹คํ–‰ === ");
			
			ServerSocket serverSocket = null; 
			Socket socket = null; 
			
			try {
				serverSocket = new ServerSocket(5001);
				socket = serverSocket.accept();
				System.out.println("ํฌํŠธ ๋ฒˆํ˜ธ - 5001 ํ• ๋‹น ์™„๋ฃŒ");
				
				// 1. ํด๋ผ์ด์–ธํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ์ž…๋ ฅ ์ŠคํŠธ๋ฆผ ํ•„์š” 
				// 2. ํด๋ผ์ด์–ธํŠธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ถœ๋ ฅ ์ŠคํŠธ๋ฆผ ํ•„์š” 
				// ์„œ๋ฒ„์ธก - ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ๋ฐ›๊ธฐ ์œ„ํ•œ ์ž…๋ ฅ ์ŠคํŠธ๋ฆผ ํ•„์š”
				
				BufferedReader socketReader = 
						new BufferedReader(new InputStreamReader(socket.getInputStream()));
				PrintWriter socketWriter = 
						new PrintWriter(socket.getOutputStream(), true);
				BufferedReader keyboardReader =
						new BufferedReader(new InputStreamReader(System.in));
				
				
				// ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋”ฉ ๊ฐœ๋…์— ํ™•์žฅ 
				// ํด๋ผ์ด์–ธํŠธ๋กœ ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์Šค๋ ˆ๋“œ 
				Thread readThread = new Thread(() -> {
					try {
						String clientMessage;
						while( (clientMessage = socketReader.readLine()) != null ) {
							System.out.println("์„œ๋ฒ„์ธก ์ฝ˜์†” : " + clientMessage);
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}); 
				
				// ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ์Šค๋ ˆ๋“œ ์ƒ์„ฑ 
				Thread writeThread = new Thread(() -> {
					try {
						String serverMessage; 
						while( ( serverMessage = keyboardReader.readLine() ) != null) {
							// 1. ๋จผ์ € ํ‚ค๋ณด๋“œ๋ฅผ ํ†ตํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  
							// 2. ์ถœ๋ ฅ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด์•ผ ํ•œ๋‹ค.
							socketWriter.println(serverMessage);
						}
						
					} catch (Exception e2) {
						
					}
				});
				
				// ์Šค๋ ˆ๋“œ ๋™์ž‘ -> start() ํ˜ธ์ถœ 
				readThread.start();
				writeThread.start();
				
				// Thread join() ๋ฉ”์„œ๋“œ๋Š” ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋ ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋„๋ก ํ•˜๋Š” 
				// ๊ธฐ๋Šฅ์„ ์ œ๊ณต ํ•œ๋‹ค. 
				readThread.join();
				writeThread.join();
				
				System.out.println("--- ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ --- ");
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					socket.close();
					serverSocket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
	}

}// end of class

Thread์˜ join() ๋ฉ”์„œ๋“œ - ์—ญํ• ๊ณผ ๊ธฐ๋Šฅ

1. ์Šค๋ ˆ๋“œ ๋™๊ธฐํ™”:

join() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ์ˆœ์„œ๋Œ€๋กœ ์ข…๋ฃŒ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋Š” join() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž‘์—…์„ ๋งˆ์น  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

2. ํ”„๋กœ๊ทธ๋žจ ํ๋ฆ„ ์ œ์–ด

join() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์Šค๋ ˆ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ ์ „๊นŒ์ง€ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š๋„๋ก ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ๋ชจ๋“  ์ž‘์—…์„ ์™„๋ฃŒํ•˜๊ธฐ ์ „์— ์ข…๋ฃŒ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

3. ์ •ํ™•ํ•œ ์ข…๋ฃŒ ์‹œ์ 

join() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŠน์ • ์Šค๋ ˆ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ ์ „๊นŒ์ง€ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ง„ํ–‰ํ•˜์ง€ ์•Š๋„๋ก ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ •ํ™•ํ•œ ์ข…๋ฃŒ ์‹œ์ ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์ธก ์ฝ”๋“œ

โ—ผ Socket ์„ ์ƒ์„ฑํ•˜์—ฌ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
โ—ผ BufferedReader๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ๊ณ , PrintWriter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
โ—ผ ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด BufferedReader๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
โ—ผ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์Šค๋ ˆ๋“œ์™€ ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ๊ฐ๊ฐ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class MultiThreadClient {

	public static void main(String[] args) {
	
		System.out.println("### ํด๋ผ์ด์–ธ ์‹คํ–‰ ###");
		
		try {
			Socket socket = new Socket("192.168.0.48", 5000);
			System.out.println("*** connected to the Server ***");
			
			PrintWriter socketWriter = new PrintWriter(socket.getOutputStream(), true);
			BufferedReader socketReader =
					new BufferedReader(new InputStreamReader(socket.getInputStream()));
			BufferedReader keyboarReader =
					new BufferedReader(new InputStreamReader(System.in));
			
			// ์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์Šค๋ ˆ๋“œ 
			Thread readThread = new Thread(() -> {
				// while <---- 
				try {
					String serverMessage;
					while( (serverMessage = socketReader.readLine()) != null ) {
						System.out.println("์„œ๋ฒ„์—์„œ ์˜จ MSG : " + serverMessage);
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			});
			
			// ์„œ๋ฒ„์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ์Šค๋ ˆ๋“œ 
			Thread writeThread = new Thread(() -> {
				try {
					
					String clientMessage; 
					while( (clientMessage = keyboarReader.readLine()) != null) {
						// 1. ํ‚ค๋ณด๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‘์šฉํ”„๋กœ๊ทธ๋žจ ์•ˆ์œผ๋กœ ์ž…๋ ฅ ๋ฐ›์•„์„œ 
						// 2. ์„œ๋ฒ„์ธก ์†Œ์ผ“๊ณผ ์—ฐ๊ฒฐ ๋˜์–ด์žˆ๋Š” ์ถœ๋ ฅ ์ŠคํŠธ๋ฆผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ธ๋‹ค. 
						socketWriter.println(clientMessage);
					}
				} catch (Exception e2) {
					e2.printStackTrace();
				}
			});
			
			readThread.start();
			writeThread.start();
			
			readThread.join();
			writeThread.join();
			
			System.out.println(" ํด๋ผ์ด์–ธํŠธ ์ธก ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ");
			
		} catch (Exception e) {
		
		}

	}// end of main

}// end of class

 

์„œ๋ฒ„์ธก ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง 1๋‹จ๊ณ„ - ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•ด๋ณด๊ธฐ
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class MultiThreadServer {

	public static void main(String[] args) {

		System.out.println("========== ์„œ๋ฒ„ ์‹คํ–‰ =========");

		// ์„œ๋ฒ„์ธก ์†Œ์ผ“์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์ค€๋น„๋ฌผ
		// ์„œ๋ฒ„ ์†Œ์ผ“, ํฌํŠธ ๋ฒˆํ˜ธ

		try (ServerSocket serverSocket = new ServerSocket(5000)) {
			// ํด๋ผ์ด์–ธํŠธ ๋Œ€๊ธฐ --> ์—ฐ๊ฒฐ ์š”์ฒญ -- ์†Œ์ผ“ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ(ํด๋ผ์ด์–ธํŠธ์™€ ์—ฐ๊ฒฐ๋œ ์ƒํƒœ)
			Socket socket = serverSocket.accept();
			System.out.println("---- client connected ----");
			
			// ํด๋ผ์ด์–ธํŠธ์™€ ํ†ต์‹ ์„ ์œ„ํ•œ ์ŠคํŠธ๋ฆผ์„ ์„ค์ • (๋Œ€์ƒ ์†Œ์ผ“์„ ์–ป์—ˆ๋‹ค)
			BufferedReader readerStream = 
					new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			PrintWriter writerStream = 
					new PrintWriter(socket.getOutputStream(), true);// true -> (์˜คํ†  + ์—ญํ• ์„ ํ•ด์คŒ)
			
			// ํ‚ค๋ณด๋“œ ์ŠคํŠธ๋ฆผ ์ค€๋น„
			BufferedReader keyboardReader = 
					new BufferedReader(new InputStreamReader(System.in)); // ํ‚ค๋ณด๋“œ -> System.in
			
			// ์Šค๋ ˆ๋“œ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค
			startReadThread(readerStream);
			startWriteThread(writerStream, keyboardReader);
			
			System.out.println("main ์Šค๋ ˆ๋“œ ์ž‘์—… ์™„๋ฃŒ...");

		} catch (Exception e) {

		}

	}// end of main
		//////////////////////////////////////////////

	// ํด๋ผ์ด์–ธํŠธ๋กœ ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์Šค๋ ˆ๋“œ ๋ถ„๋ฆฌ
	private static void startReadThread(BufferedReader bufferedReader) {

		Thread readThread = new Thread(() -> {
			try {

				String clientMessage;
				while ((clientMessage = bufferedReader.readLine()) != null) {
					// ์„œ๋ฒ„์ธก ์ฝ˜์†”์— ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฌธ์ž ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ
					System.out.println("ํด๋ผ์ด์–ธํŠธ์—์„œ ์˜จ MSG" + clientMessage);
				}

			} catch (Exception e) {
				e.printStackTrace();
			}
		});
		readThread.start(); // ์Šค๋ ˆ๋“œ ์‹คํ–‰ -> run() ๋ฉ”์„œ๋“œ ์ง„ํ–‰
		// ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ๋Œ€๊ธฐ ์ฒ˜๋ฆฌ --> join() --> ๊ณ ๋ฏผ --> 2๋ฒˆ์— ๋ฐ˜๋ณต ๋  ๋“ฏ??
		waitForThreadToEnd(readThread);

	}

	// ์„œ๋ฒ„์ธก์—์„œ -> ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ธฐ๋Šฅ
	private static void startWriteThread(PrintWriter printWriter, BufferedReader keyboardReader) {

		Thread writeThread = new Thread(() -> {
			try {
				String serverMessage;
				while ((serverMessage = keyboardReader.readLine()) != null) {
					printWriter.println(serverMessage);
					printWriter.flush();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
		writeThread.start();
		// ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ๋Œ€๊ธฐ
	}

	// ์›Œ์ปค ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฉ”์„œ๋“œ
	private static void waitForThreadToEnd(Thread thread) {
		try {
			thread.join();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}// end of class

waitForThreadToEnd(writeThread); ← ์ œ๊ฑฐ ๋Œ€์ƒ or ๋ฆฌํŒฉํ† ๋ง ๋Œ€์ƒ

์„œ๋ฒ„์ธก ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง 2๋‹จ๊ณ„ - ์ƒ์† ํ™œ์šฉ
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

// ์ƒ์†์— ํ™œ์šฉ
public abstract class AbstractServer {

	private ServerSocket serverSocket;
	private Socket socket;
	private BufferedReader readerStream;
	private PrintWriter writerStream;
	private BufferedReader keyboardReader;

	// set ๋ฉ”์„œ๋“œ
	// ๋ฉ”์„œ๋“œ ์˜์กด ์ฃผ์ž…(๋ฉค๋ฒ„ ๋ณ€์ˆ˜์— ์ฐธ์กฐ ๋ณ€์ˆ˜ ํ• ๋‹น)
	protected void setServerSocket(ServerSocket serverSocket) {
		this.serverSocket = serverSocket;
	}

	// ๋ฉ”์„œ๋“œ ์˜์กด ์ฃผ์ž…(๋ฉค๋ฒ„ ๋ณ€์ˆ˜์— ์ฐธ์กฐ ๋ณ€์ˆ˜ ํ• ๋‹น)
	protected void setSocket(Socket socket) {
		this.socket = socket;
	}

	// get ๋ฉ”์„œ๋“œ
	protected ServerSocket getServerSocket() {
		return this.serverSocket;
	}
	
	// ์‹คํ–‰์— ํ๋ฆ„์ด ํ•„์š”ํ•˜๋‹ค. (์ˆœ์„œ๊ฐ€ ์ค‘์š”)
	public final void run() {
		// 1. ์„œ๋ฒ„ ์…‹ํŒ… - ํฌํŠธ ๋ฒˆํ˜ธ ํ• ๋‹น
		try {
			setupServer();
			connection();
			setupStream();
			startService(); // ๋‚ด๋ถ€์ ์œผ๋กœ while ๋™์ž‘
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			cleanup();
		}
	}
	
	// 1. ํฌํŠธ ๋ฒˆํ˜ธ ํ• ๋‹น (๊ตฌํ˜„ ํด๋ž˜์Šค์—์„œ ์ง์ ‘ ์„ค๊ณ„)
	protected abstract void setupServer() throws IOException;
	
	// 2. ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ๋Œ€๊ธฐ ์‹คํ–‰ (๊ตฌํ˜„ ํด๋ž˜์Šค)
	protected abstract void connection() throws IOException;
	
	// 3. ์ŠคํŠธ๋ฆผ ์ดˆ๊ธฐํ™” (์—ฐ๊ฒฐ๋œ ์†Œ์ผ“์—์„œ ์ŠคํŠธ๋ฆผ์„ ๋ฝ‘์•„์•ผ ํ•จ) - ์—ฌ๊ธฐ์„œ ํ•จ(๊ทธ๋ž˜์„œ private๋กœ ์„ค์ •ํ•จ)
	private void setupStream() throws IOException {
		readerStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		writerStream = new PrintWriter(socket.getOutputStream(),true);
		keyboardReader = new BufferedReader(new InputStreamReader(System.in));
	}
	// 4. ์„œ๋น„์Šค ์‹œ์ž‘
	private void startService() {
		Thread readThread = createReadThread();
		Thread writeThread = createWriteThread();
		
		readThread.start();
		writeThread.start();
		
		try {
			readThread.join();
			writeThread.join();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private Thread createReadThread() { 
		return new Thread(() -> {
			try {
				String msg;
				while((msg = readerStream.readLine()) != null) {
					// ์„œ๋ฒ„์ธก ์ฝ˜์†”์— ์ถœ๋ ฅ
					System.out.println("ํด๋ผ์ด์–ธํŠธ ์ธก msg : " + msg);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
	}
	
	// ์บก์Šํ™”
	private Thread createWriteThread() {
		return new Thread(() -> {
			try {
				String msg;
				// scnner.nextLine(); <-- ๋ฌดํ•œ ๋Œ€๊ธฐ(์‚ฌ์šฉ์ž๊ฐ€ ์ฝ˜์†”์— ๊ฐ’ ์ž…๋ ฅ๊นŒ์ง€ ๋Œ€๊ธฐ) ...
				
				// ์„œ๋ฒ„์ธก ํ‚ค๋ณด๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ์ค„๋ผ์ธ์œผ๋กœ ์ฝ์Œ
				while((msg = keyboardReader.readLine()) != null) {
					// ํด๋ผ์ด์–ธํŠธ์™€ ์—ฐ๊ฒฐ๋œ ์†Œ์ผ“์—๋‹ค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋ƒ„
					writerStream.println(msg);
					writerStream.flush();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
	}
	
	// ์บก์Šํ™” - ์†Œ์ผ“ ์ž์› ์ข…๋ฃŒ
	private void cleanup() {
		try {
			if(socket != null) {
				socket.close();
			}
			if(serverSocket != null) {
				serverSocket.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

 

๊ตฌํ˜„ ํด๋ž˜์Šค - AbstractServer ์ƒ์† ํ™œ์šฉ
import java.io.IOException;
import java.net.ServerSocket;

public class MyThreadServer extends AbstractServer {

	@Override
	protected void setupServer() throws IOException {
		// ์ถ”์ƒ ํด๋ž˜์Šค --> ๋ถ€๋ชจ --> ์ž์‹ (๋ถ€๋ชจ ๊ธฐ๋Šฅ์— ํ™•์žฅ ๋˜๋Š” ์‚ฌ์šฉ)
		// ์„œ๋ฒ„์ธก ์†Œ์ผ“ ํ†ต์‹  -- ์ค€๋น„๋ฌผ : ์„œ๋ฒ„ ์†Œ์ผ“ 
		super.setServerSocket(new ServerSocket(5000));
		System.out.println(">>> Server started on Port 5000 <<<");
	}

	@Override
	protected void connection() throws IOException {
		// ์„œ๋ฒ„ ์†Œ์ผ“.accept() ํ˜ธ์ถœ์ด๋‹ค !!!
		super.setSocket(super.getServerSocket().accept());
	}

	public static void main(String[] args) {
		MyThreadServer myThreadServer = new MyThreadServer();
		myThreadServer.run();
	}
	
}

๋ณต์žกํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์ถ”์ƒ ํด๋ž˜์Šค์™€ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” ๋‹จ์ผ ํด๋ž˜์Šค ์„ค๊ณ„๊ฐ€ ๋” ์ ํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์„ค๊ณ„๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

 

๋„์ „ ๊ณผ์ œ - ํด๋ผ์ด์–ธํŠธ ์ธก ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง
1๋‹จ๊ณ„, 2๋‹จ๊ณ„๋กœ ์ง„ํ–‰ํ•ด ๋ณด๊ธฐ

ํด๋ผ์ด์–ธํŠธ ์ธก ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง 1 ๋‹จ๊ณ„

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

// 1๋‹จ๊ณ„ - ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌ ํ•ด์„œ ๋ฆฌํŒฉํ† ๋ง ์ง„ํ–‰
public class MultiThreadClient2 {

	// ๋ฉ”์ธ ํ•จ์ˆ˜
	public static void main(String[] args) {
		System.out.println("### ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰ ###");

		try (Socket socket = new Socket("localhost", 5000)) { // ํด๋ผ์ด์–ธํŠธ๋Š” socket๋งŒ ์žˆ์œผ๋ฉด ๋จ
			System.out.println("connected to the server !!");

			// ์„œ๋ฒ„์™€ ํ†ต์‹ ์„ ์œ„ํ•œ ์ŠคํŠธ๋ฆผ ์ดˆ๊ธฐํ™”
			BufferedReader bufferedReader = 
					new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintWriter printWriter = 
					new PrintWriter(socket.getOutputStream());
			BufferedReader keyboardReader =
					new BufferedReader(new InputStreamReader(System.in));
			
			// ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ -> main๊ฐ€ ํ•จ  // ์›Œ์ปค 1,2๊ฐ€ ์ƒ์„ฑ๋จ 
			startReadThread(bufferedReader);
			startWriteThread(printWriter, keyboardReader); 
			// ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ๊ธฐ๋‹ค๋ ค๋Š” ์–ด๋””์— ์žˆ์ง€?? -> ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง
			// startWriteThread() <-- ๋‚ด๋ถ€์— ์žˆ์Œ
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}// end of main

	// 1. ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์Šค๋ ˆ๋“œ ์‹œ์ž‘ ๋ฉ”์„œ๋“œ ์ƒ์„ฑ
	private static void startReadThread(BufferedReader reader) {

		Thread readThread = new Thread(() -> {
			try {
				String msg;
				while ((msg = reader.readLine()) != null) {
					System.out.println("์„œ๋ฒ„์—์„œ ์˜จ msg : " + msg);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
		readThread.start();
	}

	// 2. ํ‚ค๋ณด๋“œ์—์„œ ์ž…๋ ฅ์„ ๋ฐ›์•„ ํด๋ผ์ด์–ธํŠธ ์ธก์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ์Šค๋ ˆ๋“œ
	private static void startWriteThread(PrintWriter writer, BufferedReader keyboardReader) {

		Thread writerThread = new Thread(() -> {
			try {
				String msg;
				while ((msg = keyboardReader.readLine()) != null) {
					// ์ „์†ก
					writer.println(msg);
					writer.flush();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
		writerThread.start();
		
		
	}

}// end of class

ํด๋ผ์ด์–ธํŠธ ์ธก ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง 2๋‹จ๊ณ„ (์ƒ์† ํ™œ์šฉ)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

// 2๋‹จ๊ณ„ - ์ƒ์† ํ™œ์šฉ ๋ฆฌํŒฉํ† ๋ง ๋‹จ๊ณ„
public abstract class AbstractClient {

	
	private Socket socket;
	private BufferedReader readerStream;
	private PrintWriter writerStream;
	private BufferedReader keyboardReader;

	// set
	protected void setSocket(Socket socket) {
		this.socket = socket;
	}


	// get
	protected Socket getSocket() {
		return this.socket;
	}

	public final void run() {
		try {
			connection();
			setupStream();
			startService();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			cleanup();
		}
	}
	

	// ์—ฐ๊ฒฐ ๋Œ€๊ธฐ
	protected abstract void connection() throws IOException;
	
	// ์ŠคํŠธ๋ฆผ ์ดˆ๊ธฐํ™”
	private void setupStream() throws IOException {
		readerStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		writerStream = new PrintWriter(socket.getOutputStream());
		keyboardReader = new BufferedReader(new InputStreamReader(System.in));
	}

	// ์„œ๋น„์Šค ์‹œ์ž‘
	private void startService() {
		Thread readThread = createReadThread();
		Thread writeThread = createWriteThread();

		readThread.start();
		writeThread.start();

		try {
			readThread.join();
			writeThread.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

	private Thread createReadThread() {
		return new Thread(() -> {
			try {
				String msg;
				while((msg = readerStream.readLine()) != null) {
					System.out.println("์„œ๋ฒ„ ์ธก msg : " + msg);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
	}
	
	private Thread createWriteThread() {
		return new Thread(() -> {
			try {
				String msg;
				while((msg = keyboardReader.readLine()) != null) {
					writerStream.println(msg);
					writerStream.flush();
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		
		});
	}
	
	private void cleanup() {
		try {
			if(socket != null) {
				socket.close();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}// end of class
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

// 2-1 ์ƒ์†์„ ํ™œ์šฉํ•œ ๊ตฌํ˜„ ํด๋ž˜์Šค ์„ค๊ณ„ ํ•˜๊ธฐ 
public class MyClient extends AbstractClient {

	@Override
	protected void connection() throws IOException {
		super.setSocket(new Socket("localhost", 5000));
	}

	public static void main(String[] args) {
		MyClient myClient = new MyClient();
		myClient.run();
	}

}

์‹คํ–‰ ๊ฒฐ๊ณผ______

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ