본문 바로가기
☁︎KOSTA/☂︎KOSTA-JAVA

[KOSTA] Spring 기반 Cloud 서비스 구현 개발자 양성 (Day 22) - socket network 실습

by 하_센세 2022. 8. 30.

2022.08.30 [TUE]

- Day 22- 

 

수업 주요 목차

  • socket network 실습

🤖Review

Socket : 네트워크 연결의 양끝단위 (end point) 로서 통신을 위한 인터페이스를 의미

  ex) 전화기

 

client 의 예 )

Socket(server ip,port)

socket.getOutputStream() => 서버로 출력하기 위한 스트림

socket.getInputStream() => 서버에서 입력받기 위한 스트림

 

 ServerSocket : 서버에서 생성하는 서버소켓 

  ex) 대표전화의 역할, 접수처의 역할

  accept() : Socket => 클라이언트의 접속을 대기하다 클라이언트가 접속하면 실행

  일반 Socket을 return해준다.

  이 일반 socket이 클라이언트와 통신하게 된다.

 


 

🔎 Eclipse 실습 내용

 

1. step4

  • (Day21의) step3과 서버, 클라이언트가 동일
  • 그러나 클라이언트 측에서 실행시 콘솔로부터 입력받아 서버로 메세지를 출력하는 방식으로 업데이트한다. (System.in < Scanner)

-Server

package step4.server;

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

import common.IP;

public class NetServer4 implements IP {
	public void go() throws IOException {
		ServerSocket ss=null;
		try {
			ss=new ServerSocket(5432);
			System.out.println("**NetServer4 starts");
			while(true) {
				Socket socket=ss.accept(); //대기하다가 움직이는 것
				String clientInfo="["+socket.getInetAddress().toString();
				System.out.println(clientInfo+"] 님이 입장하셨습니다.");
				BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
				System.out.println(clientInfo+"님의 메세지: "+br.readLine());
				socket.close();
			}
		} finally {
			if(ss!=null) {
				ss.close();
			}
		}
	}
	public static void main(String[] args) {
		try {
			new NetServer4().go();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

-Client

package step4.client;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import common.IP;

public class NetClient4 implements IP {
	public void go() throws UnknownHostException, IOException {
		Socket socket = null;
		Scanner scanner=null; 원래는 Scanner scanner= new Scanner(System.in); 이렇게 썼었음
		try {
			scanner = new Scanner(System.in);
			socket = new Socket(IP.INST, 5432);
			String serverInfo = socket.getInetAddress().toString();
			System.out.println("["+serverInfo + "] 서버에 입장하셨습니다.");
			PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
			System.out.print("입력할 메세지: ");
//			String message=scanner.nextLine(); 강사님은 이렇게 하심
//			pw.println(message);
//			System.out.println(message+"메세지 전송 완료");
			pw.println(scanner.nextLine());
		} finally {
			if (socket != null) 
				socket.close();
			if (scanner != null) 
				scanner.close();				
			}		
	}

	public static void main(String[] args) {
		try {
			new NetClient4().go();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

scanner에 null 초기화 해준 이유는 나중에 finally에서 close하기위해

 

 

 

2. step5

  • EchoClient와 EchoServer
  • 1:1 지속적 대화
Client      Server
안녕 안녕 (을 받아서)
안녕 다시 되돌려 줌
야호 야호 (를 받아서)
야호 다시 되돌려 줌

 

-Server

  • 클라이언트가 접속해서 메세지를 보내면 입력받아 자신의 화면에 출력하고 다시 그 메세지를 클라이언트에 출력하는 역할을 지속한다.
  • 클라이언트가 exit이라는 문자열을 전송하면 종료 메세지를 받아들여 서비스는 종료한다.
package step5.server;

import java.io.BufferedReader;

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

import common.IP;

public class EchoServer implements IP {
	public void go() throws IOException {
		ServerSocket serverSocket = null;
		Socket socket=null;
		try {
			serverSocket = new ServerSocket(5432);
			System.out.println("EchoServer starts");
			socket = serverSocket.accept();
			String clientInfo=socket.getInetAddress().toString();
			System.out.println("["+clientInfo+"] 님이 입장하셨습니다.");
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintWriter pw=new PrintWriter(socket.getOutputStream(),true); // 
			while (true) {
				String message = br.readLine();
				if (message.equals("exit")) {
					System.out.println(clientInfo+"님이 나가셨습니다.");
					break;
				}
				System.out.println("[" + clientInfo + "] 님의 메세지: "+message);
				pw.println(message);
			}
		} finally {
			if (socket != null)
				socket.close();
			if (serverSocket != null) {
				System.out.println("**서버 종료**");
				serverSocket.close();
			}
		}
	}

	public static void main(String[] args) {
		try {
			new EchoServer().go();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

-Client

  • 서버에 접속해 보낼 메세지를 콘솔에서 입력받는다.
  • 서버에 메세지를 출력한다.
  • 서버에서 메세지를 입력받는다.

 

package step5.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import common.IP;

public class EchoClient implements IP {
	public void go() throws UnknownHostException, IOException {
		Socket socket = null;
		Scanner scanner = null;
		try {
			scanner = new Scanner(System.in);
			socket = new Socket(IP.MY_IP, 5432);
			String serverInfo = socket.getInetAddress().toString();
			System.out.println("[" + serverInfo + "] 서버에 입장하셨습니다.");
			PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
			BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
			while (true) {
				System.out.print("서버에 입력할 메세지: ");
				String message = scanner.nextLine();
				pw.println(message);
				if (message.equals("exit")) {
					System.out.println("**클라이언트 종료**");
					break;
				}
				message=br.readLine();
				System.out.println("서버에서 입력받은 메세지: "+message);
			}
		} finally {
			if (socket != null)
				socket.close();
			if (scanner != null)
				scanner.close();

		}
	}

	public static void main(String[] args) {
		try {
			new EchoClient().go();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

 

 

🤮error🤮

 

서버, 클라이언트 모두 인풋, 아웃풋 스트림을 만들어주고 주고 받아야하는데 BufferedReader, PrintWriter을 하나씩만 써줬었음. (구)조원의 도움으로 이 개념 이후한 뒤에는 혼자 코드 짤 수 있었다! While 위치만 바꿔주면 되는 거였는데 역시 처음하는 건 해매도 너무 해맨다...ㅠ

 

 

-강사님 풀이

-server

package step5_1.server;

import java.io.BufferedReader;

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

import common.IP;

public class EchoServer implements IP {
	public void go() throws IOException {
		ServerSocket serverSocket = null;
		Socket socket = null;
		try {
			serverSocket = new ServerSocket(5432);
			System.out.println("**EchoServer 실행중**");
			socket = serverSocket.accept();
			String clientInfo = socket.getInetAddress().toString();
			System.out.println(clientInfo + "]님이 입장하셨습니다.");
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
			while (true) {
				String message = br.readLine();
				System.out.println(clientInfo + "님의 메세지: " + message);
				pw.println(message+"**server**");
				if (message == null || message.equalsIgnoreCase("exit")) {
					System.out.println(clientInfo + "님이 나가셨습니다.");
					break;
				}
			}
		} finally {
			if (socket != null)
				socket.close();
			if (serverSocket != null)
				serverSocket.close();
		}
	}

	public static void main(String[] args) {
		try {
			new EchoServer().go();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

-client

package step5_1.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import common.IP;

public class EchoClient implements IP {
	public void go() throws UnknownHostException, IOException {
		Socket socket = null;
		Scanner scanner = null;
		try {
			scanner = new Scanner(System.in);
			socket = new Socket(IP.MY_IP, 5432);
			String serverInfo = socket.getInetAddress().toString();
			System.out.println("[" + serverInfo + "] 서버에 입장하셨습니다.");
			PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
			BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
			while (true) {
				System.out.print("서버에 입력할 메세지: ");
				String message = scanner.nextLine(); // 서버에 보낼 메세지를 콘솔에서 입력받는다.
				pw.println(message); // 서버에 메세지를 출력한다.
				if (message.equals("exit")) {
					System.out.println("**EchoClient 종료합니다**");
					break;
				}
				System.out.println("서버에서 입력받은 메세지: "+br.readLine()); // 서버에서 입력받은 메세지
			}
		} finally {
			if (socket != null)
				socket.close();
			if (scanner != null)
				scanner.close();
		}
	}

	public static void main(String[] args) {
		try {
			new EchoClient().go();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

3. step6 (성공! 강사님이 추가하신 것들은 실행시 에러가 나는 건 아님!)

 

-MultiServer

  • ServerSocket(대표전화) accept()를 통해 클라이언트가 접속하면 해당 클라이언트와 연결된 Socket(직원 전화기)를 반환받는다.
  • 이를 ServerWorker 객체 생성시 할당한다.
  •  Thread를 생성해 start시키는 동작을 반복한다.
package step6.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class MultiServer {
	public void go() throws IOException {
		ServerSocket serverSocket=null;
		//Socket socket=null;
		try {
			serverSocket=new ServerSocket(5432);
			System.out.println("MultiServer 시작");
			while(true){
				Socket socket=serverSocket.accept();
				ServerWorker worker=new ServerWorker(socket);
				Thread thread=new Thread(worker);
				thread.setDaemon(true); // 이걸 안썼었음 (thread가 종료되면 같이 종료)
				thread.start();
			}
		} finally {
//			if(socket != null)
//				socket.close(); // 메세지를 주고받는 일(socket을 사용하는 건 ServerWorker)그래서 socket 닫아주는 것도 ServerWorker에서
			if(serverSocket != null)
				serverSocket.close();
		}
	}
	public static void main(String[] args) {
		try {
			new MultiServer().go();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

 

-ServerWorker 

  • 실제로 클라이언트에게 메아리 서비스를 제공하는 역할
  • 클라이언트가 보낸 메세지를 입력받아 자신의 콘솔에 출력하고 다시 그 메세지를 해당 클라이언트에게 출력하는 역할
  • exit가 전달되면 break로 빠져나와 스레드를 종료한다.
package step6.server;

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

import java.net.Socket;

public class ServerWorker implements Runnable {
	private Socket socket;
	private String clientInfo;
	public ServerWorker(Socket socket) {
		super();
		this.socket = socket;
		this.clientInfo=socket.getInetAddress().toString();
		System.out.println(clientInfo + "님이 접속하셨습니다.");
	}

	@Override
	public void run() {
		try {
			echo();
		} catch (IOException e) {
			//e.printStackTrace();
			System.out.println(clientInfo+"님 강제종료함"+e.getMessage());
		} finally {
			System.out.println(clientInfo+"님이 나가셨습니다");
			
		}
	}

	public void echo() throws IOException {
		//String clientInfo = socket.getInetAddress().toString(); 난 여기 썼었음
		//System.out.println(clientInfo + "님이 접속하셨습니다.");
		try{
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
		while (true) {
			String message = br.readLine();
			System.out.println(clientInfo + "님이 보내신 메세지: " + message);
			pw.println(message+"**multiserver**");
			if (message==null||message.equalsIgnoreCase("exit")) {
				//System.out.println(clientInfo + "님이 퇴장하셨습니다.");
				break;
			}
		}
	} finally {
		if (socket != null)
			socket.close();
		}
	}
}

 

 

 

 

 

 

//오늘의 숙제

IO + Thread + Network 복습