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 복습