3주차 12/14 수

하이·2022년 12월 14일
0

수업

목록 보기
7/41
post-custom-banner

계획
~ 12/14 : Java 기초 + 기본
12/15 ~ 19 (3일) : 연습문제 + 정리
12/20 ~ 28 (7일) : Database + SQL
12/29 ~ 1/4 (5일) : Java(FX) + Database (JDBC) + Mybatis
1/5 ~ 1/11 (5일) : 개인 프로젝트 (Java + Database)
=>Web으로 넘어감

다중 Echo program

공유객체 -> chatting

server socket이 만들어지고 accetp()라는 메소드 호출 : 클라이언트의 연결을 기다리고 있어야함 - 이 상태로 HOLD

Socket이 만들어지면 이 소켓을 가지고 Server는 항상 accept를 하고 있어야해서 Thread에게 통신을 부탁

package exam03;

import javafx.application.Application;
import javafx.stage.Stage;

public class Exam03_MultiEchoClient extends Application{			// 1. 상속

	@Override
	public void start(Stage primaryStage) throws Exception {		// 2. 오버라이딩 4. 창 이름 바꾸기(안 바꿔도 됨)
		// 화면 구성을 해요
		// primaryStage => 얘가 실제 window에요
		
		
		// 화면을 구성할 layout 먼저 만들기								// 5.
		// 우리는 화면 구성을 BorderPane을 이용해서 구성할 거에요 (동서남북 중앙 화면 5등분)
		
		primaryStage.show();//화면 띄움
		
		
		
	}				
	
	public static void main(String[] args) {						//3. main method
		// main thread에 의해서 최초로 실행되는 method
		// entry point
		// GUI Thread를 하나 생성할 거에요
		launch();
		
	}

	
}
		// 화면을 구성할 layout 먼저 만들기								// 5.
		// 우리는 화면 구성을 BorderPane을 이용해서 구성할 거에요 (동서남북 중앙 화면 5등분)
		BorderPane root = new BorderPane();
		
		// 이런 layout을 이용해서 화면에 보여줄 장면(Scene)을 만든다
		Scene scene = new Scene(root);	// 장면 객체 필요, 이 장면을 윈도우에 내용을 붙인다(무대에 올린다)
		
		// 이제 만들어진 장면을 Window에 넣는다
		primaryStage.setScene(scene);
		
		primaryStage.show();//화면 띄움
		
		// 화면을 구성할 layout 먼저 만들기								// 5.
		// 우리는 화면 구성을 BorderPane을 이용해서 구성할 거에요 (동서남북 중앙 화면 5등분)
		BorderPane root = new BorderPane();
		root.setPrefSize(700, 500);									// 7.
		
		// 실제 화면구성을 해보자										// 6.
//		TextArea textArea = new TextArea();							// 지역변수로 start에 하면 다른 method에 사용할 수 없어 곤란해짐 => 필드로 올리자
		textArea = new TextArea();	
		root.setCenter(root);	// 가운데에 textarea가 붙음
		
		startBtn = new Button("서버기동!!");							// 8.
		startBtn.setPrefSize(150, 40);
		// 버튼의 이벤트 처리코드를 먼저 작성
		startBtn.setOnAction(e -> {
			// 이벤트 처리 코드가 나옴 Java Lambda
		});
		
		startBtn = new Button("서버중지!!");							// 8.
		startBtn.setPrefSize(150, 40);
		// 버튼의 이벤트 처리코드를 먼저 작성
		startBtn.setOnAction(e -> {
			// 이벤트 처리 코드가 나옴 Java Lambda
		});
		
		
		// BorderPane의 아래부분(Bottom)에 버튼을 부착시키고 싶어요
		// 공간은 하나인데 버튼은 2개. -> 붙일 수가 없음
		// 일단 판자(FlowPane)을 하나 만들어서 버튼 2개를 차례대로 붙이고
		// 이 판자를 BorderPane의 아래부분(Bottom)에 붙여요
		FlowPane flowPane = new FlowPane();
		// 이 판자에 버튼을 2개 붙일 거에요. 그런데 설정(Padding, 정렬)을 안 하면
		// 안 예쁨 - 보기가 좋지 않음 -> 설정이 좀 들어가야 함
		flowPane.setPadding(new Insets(10,10,10,10));	//padding(여백) 설정
		flowPane.setColumnHalignment(HPos.CENTER);		// 정렬
		flowPane.setHgap(10);
		
        
        
  • socket 생성하고 난 후 stream을 뚫어야함

최종 코드

Exam03_MultiEchoClient.java

package exam03;

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 javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class Exam03_MultiEchoClient extends Application{
	
	TextArea textArea;
	TextField ipTextField;
	Button connBtn;
	TextField idTextField;
	TextField chatTextField;
	
	Socket socket;
	PrintWriter pr;
	BufferedReader br;
	
	private void printMsg(String msg) {								// 13.
		Platform.runLater(()->{					// Thread 이용해서 Textarea에 찍는 method
			textArea.appendText(msg + "\n");
		});

	}
	
	@Override
	public void start(Stage primaryStage) throws Exception {
		
		// BorderPane생성
		BorderPane root = new BorderPane();
		root.setPrefSize(700, 500);
		
		textArea = new TextArea();
		root.setCenter(textArea);
		
		FlowPane upFlowPane = new FlowPane();
		upFlowPane.setPadding(new Insets(10,10,10,10));		//padding(여백) 설정
		upFlowPane.setColumnHalignment(HPos.CENTER);		// 정렬
		upFlowPane.setPrefSize(700, 40);
		upFlowPane.setHgap(10);
		
		ipTextField = new TextField();
		ipTextField.setPrefSize(200, 40);	
		
		connBtn = new Button("서버에 접속!!");
		connBtn.setPrefSize(150, 40);
		connBtn.setOnAction(e -> {
			// 서버에 접속해요 !
			// 특정 IP와 PORT번호를 이용해서 Socket객체 생성을 시도
			try {
				socket = new Socket(ipTextField.getText(), 7777);
				
				// 연결 버튼 누르면 하는 동작
				pr = new PrintWriter(socket.getOutputStream());	// 소켓을 통해 클라이언트쪽에서 내보냄
				br = new BufferedReader(new InputStreamReader(socket.getInputStream()));	// 데이터를 받아들이는 통로
				
			} catch (UnknownHostException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
		});
		
		upFlowPane.getChildren().add(ipTextField);
		upFlowPane.getChildren().add(connBtn);
		

		FlowPane bottomFlowPane = new FlowPane();
		bottomFlowPane.setPadding(new Insets(10,10,10,10));		//padding(여백) 설정
		bottomFlowPane.setColumnHalignment(HPos.CENTER);		// 정렬
		bottomFlowPane.setPrefSize(700, 40);
		bottomFlowPane.setHgap(10);

		idTextField = new TextField();
		idTextField.setPrefSize(150, 40);

		chatTextField = new TextField();
		chatTextField.setPrefSize(300, 40);
		chatTextField.setOnAction(e->{
			// 채팅입력창에서 enter를 치면...
			// action event가 발생해서 이 코드가 실행됨
			String id = idTextField.getText();
			String msg = chatTextField.getText();
			
			pr.println(id + " > " + msg);	// 마차
			pr.flush();
			
			try {
				String receive = br.readLine();	// 서버가 보내준 걸 화면에 찍는다
				printMsg(receive);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		});
	
		bottomFlowPane.getChildren().add(idTextField);
		bottomFlowPane.getChildren().add(chatTextField);
		
		root.setTop(upFlowPane);
		root.setBottom(bottomFlowPane);
		
		Scene scene = new Scene(root);
		
		primaryStage.setScene(scene);
		primaryStage.setTitle("Echo Client Program");
		primaryStage.show();
		
	}

	public static void main(String[] args) {
		launch();
	}
	
}

Exam03_MultiEchoServer.java

package exam03;


import java.beans.EventHandler;
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 javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;


//class MyServerRunnable implements Runnable {					// 10. 스레스 생성을 위해 class 생성
//
//	@Override
//	public void run() {
//		// TODO Auto-generated method stub
//		
//	}										
//	
//	
//}

class MyRunnable implements Runnable {							// 10-1
	
	Socket socket;
	PrintWriter pr;
	BufferedReader br;
	
	
	public MyRunnable() {
		// TODO Auto-generated constructor stub
	}
		
	
	public MyRunnable(Socket socket) {
		super();
		this.socket = socket;
		try {
			this.pr = new PrintWriter(socket.getOutputStream());
			this.br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}


	@Override
	public void run() {											// 12. 클라이언트와 통신하는 코드
		
		try {
			while(true) {
				String msg = br.readLine();
				
				pr.println(msg);
				pr.flush();
			}				
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}			

public class Exam03_MultiEchoServer extends Application{			// 1. 상속

	TextArea textArea;
	Button startBtn;
	Button stopBtn;
	
	ServerSocket server;
	
	
	private void printMsg(String msg) {								// 13.
		Platform.runLater(()->{
			textArea.appendText(msg + "\n");
		});

	}
	
	
	
	@Override
	public void start(Stage primaryStage) throws Exception {		// 2. 오버라이딩 4. 창 이름 바꾸기(안 바꿔도 됨)
		// 화면 구성을 해요
		// primaryStage => 얘가 실제 window에요
		
		
		// 화면을 구성할 layout 먼저 만들기								// 5.
		// 우리는 화면 구성을 BorderPane을 이용해서 구성할 거에요 (동서남북 중앙 화면 5등분)
		BorderPane root = new BorderPane();
		root.setPrefSize(700, 500);									// 7.
		
		// 실제 화면구성을 해보자										// 6.
//		TextArea textArea = new TextArea();							// 지역변수로 start에 하면 다른 method에 사용할 수 없어 곤란해짐 => 필드로 올리자
		textArea = new TextArea();	
		root.setCenter(textArea);	// 가운데에 textarea가 붙음
		
		startBtn = new Button("서버기동!!");							// 8.
		startBtn.setPrefSize(150, 40);
		// 버튼의 이벤트 처리코드를 먼저 작성
		startBtn.setOnAction(e -> {
			// 이벤트 처리 코드가 나옴 Java Lambda
			// 여기가 실행될 동안 window는 잠시 block된다
			// 하필이면..클라이언트의 접속을 무한정 기다리는 코드가 나와야함
			// 이 문제를 해결하기 위해.. Thread를 생성해서 사용함			// 10.
//			MyServerRunnable r = new MyServerRunnable();
		
			(new Thread(()->{										// 10. 시작되면 run만 하니까 축약해서 표현. 이를 Lamda. {}가 run
				try {
					// port가 다른 프로그램에서 사용되고 있는 중일 수 있기 때문에
					// 예외상황이 발생할 수 있음. 그래서 이 코드는 예외처리가 강제됨
					server = new ServerSocket(7777);	// port 번호 7777
					
					while(true) {									// 10-2 While
						Socket socket = server.accept();	// 클라이언트의 접속을 기다림!
						// 대기하고 있다가 클라이언트가 접속하면 해당 클라이언트와
						// 연결된 Socket 객체를 하나 생성해요 !
						
						// socket을 이용해서 직접 클라이언트와 통신하는 기능을 수행하는
						// Thread를 하나 생성해야 해요
						// Thread를 만들기 위한 클래스가 있어야겠죠. 클래스를 작성해보아요
						
						printMsg("새로운 클라이언트 접속 !!");			// 13-1
						
						MyRunnable r = new MyRunnable(socket);		// 10-1
						Thread t = new Thread(r);
						t.start();
					}	
								
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			})).start();							
//			t.start();												
			
		});
		
		stopBtn = new Button("서버중지!!");							// 8.
		stopBtn.setPrefSize(150, 40);
		// 버튼의 이벤트 처리코드를 먼저 작성
		stopBtn.setOnAction(e -> {
			// 이벤트 처리 코드가 나옴 Java Lambda
		});
		
		
		// BorderPane의 아래부분(Bottom)에 버튼을 부착시키고 싶어요
		// 공간은 하나인데 버튼은 2개. -> 붙일 수가 없음
		// 일단 판자(FlowPane)을 하나 만들어서 버튼 2개를 차례대로 붙이고
		// 이 판자를 BorderPane의 아래부분(Bottom)에 붙여요
		FlowPane flowPane = new FlowPane();
		// 이 판자에 버튼을 2개 붙일 거에요. 그런데 설정(Padding, 정렬)을 안 하면
		// 안 예쁨 - 보기가 좋지 않음 -> 설정이 좀 들어가야 함
		flowPane.setPadding(new Insets(10,10,10,10));	//padding(여백) 설정
		flowPane.setColumnHalignment(HPos.CENTER);		// 정렬
		flowPane.setPrefSize(700, 40);
		flowPane.setHgap(10);
		
		// 판자 설정이 끝났으니 이제 판자에 버튼을 붙여야함					//9.
		flowPane.getChildren().add(startBtn);
		flowPane.getChildren().add(stopBtn);
		
		// 판자를 BorderPane
		root.setBottom(flowPane);
		
		// 5. 이런 layout을 이용해서 화면에 보여줄 장면(Scene)을 만든다
		Scene scene = new Scene(root);	// 장면 객체 필요, 이 장면을 윈도우에 내용을 붙인다(무대에 올린다)
		
		// 5. 이제 만들어진 장면을 Window에 넣는다
		primaryStage.setScene(scene);
		primaryStage.setTitle("Echo Server Program");				// 8.
		
		primaryStage.show();			//화면 띄움	
		
	}				
	
	public static void main(String[] args) {						// 3. main method
		// main thread에 의해서 최초로 실행되는 method
		// entry point
		// GUI Thread를 하나 생성할 거에요
		launch();
		
	}

	
}


최종 결과



  • 내가 보내지 않은 데이터 받기


chatting program

Exam04_ChatServer.java

package exam04;


import java.beans.EventHandler;
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 java.util.ArrayList;
import java.util.HashMap;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;


//class MyServerRunnable implements Runnable {					// 10. 스레스 생성을 위해 class 생성
//
//	@Override
//	public void run() {
//		// TODO Auto-generated method stub
//		
//	}										
//	
//	
//}


class Shared {	// 04예제 시작
	
	ArrayList<Socket> list = new ArrayList<Socket>();	// list는 field. 공유객체 만들면 비어있는 arraylist를 하나 만든다
														// Client와 연결된 논리적 객체인 Socket
	HashMap<Socket, PrintWriter> map = new HashMap<Socket, PrintWriter>();	// <키값, value값>
	
	// method
	// 서버에 새로운 클라이언트가 접속하면..
	// 해당 클라이언트에 대한 소켓이 서버쪽에 만들어지고
	// 이 소켓을 공유객체에 저장해야 함
	// 이 작업을 아래쪽에 있는 메소드가 수행한다
	// 데이터를 저장하기 위해 Socket을 갖고와야함
	public synchronized void addClient(Socket socket) {
		list.add(socket);
		try {
			map.put(socket, new PrintWriter(socket.getOutputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	// Socket에 대한 출력통로를 Map에 넣는다
																	// 이제 통로는 thread가 아닌 공유객체가 가지고 있다
	}
	
	
	public synchronized void broadcast(String msg) {
		// 전달받은 문자열을 모든 클라이언트 PrintWriter를 통해
		// 데이터를 내보내요
		for(Socket s : list) {
			(map.get(s)).println(msg);
			(map.get(s)).flush();
		}

	}	
	
}
class MyRunnable implements Runnable {							// 10-1
	
	Socket socket;
//	PrintWriter pr;
	BufferedReader br;
	Shared shared;
	
	public MyRunnable() {
		// TODO Auto-generated constructor stub
	}
		
	
	public MyRunnable(Socket socket, Shared shared) {
		super();
		this.socket = socket;
		this.shared = shared;
		try {
//			this.pr = new PrintWriter(socket.getOutputStream());	// 공유객체 , 통로를 만들었기 때문에 Thread는 더이상 필요없음
			this.br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}


	@Override
	public void run() {											// 12. 클라이언트와 통신하는 코드
		
		try {
			while(true) {
				String msg = br.readLine();
				
				// 공유객체를 통해서 모든 클라이언트에게
				// 데이터를 내보내요 !
				shared.broadcast(msg);
				
				
//				pr.println(msg);
//				pr.flush();
			}				
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}			

public class Exam04_ChatServer  extends Application{			// 1. 상속

	TextArea textArea;
	Button startBtn;
	Button stopBtn;
	
	ServerSocket server;
	Shared shared;		// 공유객체를 필드로 설정함
	
	
	
	private void printMsg(String msg) {								// 13.
		Platform.runLater(()->{
			textArea.appendText(msg + "\n");
		});

	}
	
	
	
	@Override
	public void start(Stage primaryStage) throws Exception {		// 2. 오버라이딩 4. 창 이름 바꾸기(안 바꿔도 됨)
		// 화면 구성을 해요
		// primaryStage => 얘가 실제 window에요
		
		
		// 화면을 구성할 layout 먼저 만들기								// 5.
		// 우리는 화면 구성을 BorderPane을 이용해서 구성할 거에요 (동서남북 중앙 화면 5등분)
		BorderPane root = new BorderPane();
		root.setPrefSize(700, 500);									// 7.
		
		// 실제 화면구성을 해보자										// 6.
//		TextArea textArea = new TextArea();							// 지역변수로 start에 하면 다른 method에 사용할 수 없어 곤란해짐 => 필드로 올리자
		textArea = new TextArea();	
		root.setCenter(textArea);	// 가운데에 textarea가 붙음
		
		startBtn = new Button("서버기동!!");							// 8.
		startBtn.setPrefSize(150, 40);
		// 버튼의 이벤트 처리코드를 먼저 작성
		startBtn.setOnAction(e -> {
			// 이벤트 처리 코드가 나옴 Java Lambda
			// 여기가 실행될 동안 window는 잠시 block된다
			// 하필이면..클라이언트의 접속을 무한정 기다리는 코드가 나와야함
			// 이 문제를 해결하기 위해.. Thread를 생성해서 사용함			// 10.
//			MyServerRunnable r = new MyServerRunnable();
			
			// 공유객체를 생성해요
			shared = new Shared();
			
		
			(new Thread(()->{										// 10. 시작되면 run만 하니까 축약해서 표현. 이를 Lamda. {}가 run
				try {
					// port가 다른 프로그램에서 사용되고 있는 중일 수 있기 때문에
					// 예외상황이 발생할 수 있음. 그래서 이 코드는 예외처리가 강제됨
					server = new ServerSocket(7777);	// port 번호 7777
					
					while(true) {									// 10-2 While
						Socket socket = server.accept();	// 클라이언트의 접속을 기다림!
						// 대기하고 있다가 클라이언트가 접속하면 해당 클라이언트와
						// 연결된 Socket 객체를 하나 생성해요 !
						
						// socket을 이용해서 직접 클라이언트와 통신하는 기능을 수행하는
						// Thread를 하나 생성해야 해요
						// Thread를 만들기 위한 클래스가 있어야겠죠. 클래스를 작성해보아요
						
						printMsg("새로운 클라이언트 접속 !!");			// 13-1
						
						// 공유객체에 클라이언트 소켓을 저장한다 !
						shared.addClient(socket);
						
						MyRunnable r = new MyRunnable(socket, shared);		// 10-1
						Thread t = new Thread(r);
						t.start();
					}	
								
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			})).start();							
//			t.start();												
			
		});
		
		stopBtn = new Button("서버중지!!");							// 8.
		stopBtn.setPrefSize(150, 40);
		// 버튼의 이벤트 처리코드를 먼저 작성
		stopBtn.setOnAction(e -> {
			// 이벤트 처리 코드가 나옴 Java Lambda
		});
		
		
		// BorderPane의 아래부분(Bottom)에 버튼을 부착시키고 싶어요
		// 공간은 하나인데 버튼은 2개. -> 붙일 수가 없음
		// 일단 판자(FlowPane)을 하나 만들어서 버튼 2개를 차례대로 붙이고
		// 이 판자를 BorderPane의 아래부분(Bottom)에 붙여요
		FlowPane flowPane = new FlowPane();
		// 이 판자에 버튼을 2개 붙일 거에요. 그런데 설정(Padding, 정렬)을 안 하면
		// 안 예쁨 - 보기가 좋지 않음 -> 설정이 좀 들어가야 함
		flowPane.setPadding(new Insets(10,10,10,10));	//padding(여백) 설정
		flowPane.setColumnHalignment(HPos.CENTER);		// 정렬
		flowPane.setPrefSize(700, 40);
		flowPane.setHgap(10);
		
		// 판자 설정이 끝났으니 이제 판자에 버튼을 붙여야함					//9.
		flowPane.getChildren().add(startBtn);
		flowPane.getChildren().add(stopBtn);
		
		// 판자를 BorderPane
		root.setBottom(flowPane);
		
		// 5. 이런 layout을 이용해서 화면에 보여줄 장면(Scene)을 만든다
		Scene scene = new Scene(root);	// 장면 객체 필요, 이 장면을 윈도우에 내용을 붙인다(무대에 올린다)
		
		// 5. 이제 만들어진 장면을 Window에 넣는다
		primaryStage.setScene(scene);
		primaryStage.setTitle("Echo Server Program");				// 8.
		
		primaryStage.show();			//화면 띄움	
		
	}				
	
	public static void main(String[] args) {						// 3. main method
		// main thread에 의해서 최초로 실행되는 method
		// entry point
		// GUI Thread를 하나 생성할 거에요
		launch();
		
	}

	
}


Exam04_ChatClient

package exam04;

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 javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class Exam04_ChatClient extends Application{
	
	TextArea textArea;
	TextField ipTextField;
	Button connBtn;
	TextField idTextField;
	TextField chatTextField;
	
	Socket socket;
	PrintWriter pr;
	BufferedReader br;
	
	private void printMsg(String msg) {								// 13.
		Platform.runLater(()->{					// Thread 이용해서 Textarea에 찍는 method
			textArea.appendText(msg + "\n");
		});

	}
	
	@Override
	public void start(Stage primaryStage) throws Exception {
		
		// BorderPane생성
		BorderPane root = new BorderPane();
		root.setPrefSize(700, 500);
		
		textArea = new TextArea();
		root.setCenter(textArea);
		
		FlowPane upFlowPane = new FlowPane();
		upFlowPane.setPadding(new Insets(10,10,10,10));		//padding(여백) 설정
		upFlowPane.setColumnHalignment(HPos.CENTER);		// 정렬
		upFlowPane.setPrefSize(700, 40);
		upFlowPane.setHgap(10);
		
		ipTextField = new TextField();
		ipTextField.setPrefSize(200, 40);	
		
		connBtn = new Button("서버에 접속!!");
		connBtn.setPrefSize(150, 40);
		connBtn.setOnAction(e -> {
			// 서버에 접속해요 !
			// 특정 IP와 PORT번호를 이용해서 Socket객체 생성을 시도
			try {
				socket = new Socket(ipTextField.getText(), 7777);
				
				// 연결 버튼 누르면 하는 동작
				pr = new PrintWriter(socket.getOutputStream());	// 소켓을 통해 클라이언트쪽에서 내보냄
				br = new BufferedReader(new InputStreamReader(socket.getInputStream()));	// 데이터를 받아들이는 통로
	
				(new Thread(()->{
					while(true) {
						try {
							String receive = br.readLine();	// 서버가 보내준 걸 화면에 찍는다
							printMsg(receive);
						} catch (IOException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
					}//while()
					
				})).start();
				
				
			} catch (UnknownHostException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
		});
		
		upFlowPane.getChildren().add(ipTextField);
		upFlowPane.getChildren().add(connBtn);
		

		FlowPane bottomFlowPane = new FlowPane();
		bottomFlowPane.setPadding(new Insets(10,10,10,10));		//padding(여백) 설정
		bottomFlowPane.setColumnHalignment(HPos.CENTER);		// 정렬
		bottomFlowPane.setPrefSize(700, 40);
		bottomFlowPane.setHgap(10);

		idTextField = new TextField();
		idTextField.setPrefSize(150, 40);

		chatTextField = new TextField();
		chatTextField.setPrefSize(300, 40);
		chatTextField.setOnAction(e->{
			// 채팅입력창에서 enter를 치면...
			// action event가 발생해서 이 코드가 실행됨
			String id = idTextField.getText();
			String msg = chatTextField.getText();
			
			pr.println(id + " > " + msg);	// 마차
			pr.flush();
			
		});
	
		bottomFlowPane.getChildren().add(idTextField);
		bottomFlowPane.getChildren().add(chatTextField);
		
		root.setTop(upFlowPane);
		root.setBottom(bottomFlowPane);
		
		Scene scene = new Scene(root);
		
		primaryStage.setScene(scene);
		primaryStage.setTitle("Echo Client Program");
		primaryStage.show();
		
	}

	public static void main(String[] args) {
		launch();
	}
	
}


최종결과



IP주소 알아보기
ipconfig

  • Address already 오류 해결 방법
    netstat -ano | find "8080"
    taskkill /f /pid 10216

코테 연습
https://swexpertacademy.com/main/main.do

profile
기록의 즐거움 😆💻
post-custom-banner

0개의 댓글