계획
~ 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으로 넘어감
공유객체 -> 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);
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();
}
}
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();
}
}
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();
}
}
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