반응형

Database 용어정리

 

1. Database

 다수의 사용자들이 공용으로 사용하기 위해 저장된 데이터의 집합

 

2. Database Language

  • DDL(Data Definition Language) : 데이터베이스 구조를 정의, 수정, 삭제하는 언어(create, alter, drop)
  • DML(Data Manipulation Language): 데이터베이스 내의 자료 검색, 삽입, 갱신, 삭제를 위한 언어(select, delete, update, insert)
  • DCL(Data Control Language): 데이터에 대해 무결성을 유지, 병행 수행 제어, 보호와 관리를 위한 언어(commit, rollback, grant, revoke)

3. Schema(스키마)

  • 데이터베이스의 전체적인 구조와 제약조건에 대한 기술 정의

4. 무결성

  • 개체 무결성: 기본키는 Null값이 올 수 없으며, 중복될 수 없다.
  • 참조 무결성: 외래키는 Null값이 올 수 있으며, 부모 테이블의 기본키에 종속되어야 한다.
  • 도메인 무결성, 고유 무결성, null무결성, 키 무결성

5. View

  •  하나 이상의 테이블로부터 유도되어 만들어진 가상테이블, 실제로 기억공간을 차지하지 않으며 논리적 독립성을 제공하고 데이터 접근 제어로부터 보안성을 향상시킨다.
  • 정의된 기본 테이블이 삭제되면 뷰 또한 삭제된다.
  • 한번 정의된 뷰는 변경할 수 없으며, 삭제한 후 다시 생성해야 한다.(replace)
  • 검색은 일반 테이블과 동일한 방식으로 한다.
  • 뷰에 대한 삽입, 삭제, 갱신에 대한 제약이 따른다. 컬럼에 기본키가 포함되어 있지 않으면 삽입, 갱신, 삭제가 되지 않는다.

6. 인덱스 생성시 고려할 사항

  • 테이블의 전체 데이터 중 적은 양을 조회할 때 사용한다.
  • 테이블에 데이터가 적을수록 인덱스의 효율은 떨어진다.
  • 데이터의 유일성이 높을수록, 데이터의 범위가 넓을수록 인덱스의 효율이 올라간다.
  • Null이 적은 컬럼이 인덱스 효율이 좋다.
  • 결합 인덱스의 경우 자주 사용되는 컬럼을 앞쪽에 배치한다.

Database Q/A

Q. SELECT문은 무엇입니까?

A. SELECT문은 사용자들이 데이터베이스 내 테이블에서 값들을 선택할 수 있도록 합니다. 데이터베이스 테이블에서 어떤 값들을 선택하는 가는 SQL질의 내 다양한 조건에 달려 있습니다.

 

Q. 전체 이름이 아닌 이름의 일부로 값을 비교할 수 있는 방법은 무엇입니까? (LIKE절)

A. SELECT * FROM user WHERE name LIKE '%희%';  

(name에 문자열 희를 포함하는 name레코드들을 가진 레코드 셋을 반환합니다.)

 

Q. Insert문은 무엇입니까

A. Database에 정보를 삽입하는 문입니다.

EX) INSERT INTO 테이블명 (INSERT할 컬럼) VALUES (데이터);

 

Q. Database에서 레코드는 어떻게 삭제합니까? (DELETE문)

A. DELETE문은 데이터베이스에서 레코드 또는 특정 컬럼의 값을 삭제합니다.

EX) DELETE FROM 테이블명 WHERE 조건

 

Q. 테이블에서 어떻게 중복이 없는(뼐개) 항목을 얻을 수 있습니까?(DISTINCT)

A. DISTINCT는 중복된 결과를 제거하고 하나만 원하고자 할 때 쓰이는 문법입니다. Database table에 특정 값 a,b,a,c가 있으면 a,b,c만 나오게 할 수 있습니다. 그러나 distinct를 사용시 temp tablespace에 임시로 저장하고 작업하는 방식이라 시스템에 부하를 줄 수 있다.

EX) SELECT DISTINCT 테이블명 WHERE 조건

 

Q. 특정 기준을 통하여 정렬된 결과를 얻는 방법은 무엇입니까? (ORDER BY)

A. 프로그램에서 ORDER BY 키워드를 사용하여 정렬하고 정렬된 결과를 반환하여 정렬을 수행할 수 있습니다.

ORDER BY만 하면(Default) 오름차순 정렬이되고 DESC 값을 주게 되면 내림차순 할 수 있습니다.

 

Q. 테이블의 전체 레코드 수를 어떻게 얻을 수 있습니까?

A. SELECT COUNT(*) FROM user WHERE age > 40 에서 count키워드를 사용하게 되면 카운트 수를 얻을 수 있습니다.

 

Q. GROUP BY는 무엇입니까?

A. GROUP BY는 집계함수로 컬럼의 데이터들을 그룹화하여 집계할 수 있습니다.

EX) SELECT 선택 FROM 테이블명 WHERE 조건 GROUP BY 그룹화할 콜럼

 

Q. 테이블을 DROP하는 것과 Truncate, 그리고 테이블 내 모든 레코드를 Delete하는 것의 차이점은 무엇입니까?

A.

1. DELETE 명령어는 데이터는 지워지지만 테이블 용량은 줄어들지 않습니다. 원하는 데이터만 지울 수 있습니다. 삭제 후 RollBack이 가능합니다.

2. DELETE TABLE은 로그되는 작업이기 때무넹 삭제되는 각 행은 트랜젝션 로그에 기록되고 이것은 작업을 느리게 합니다.

 

3. TRUNCATE 명령어는 용량이 줄어들고, 인덱스 등도 모두 삭제됩니다. 테이블 삭제하지 않고 데이터만 삭제합니다. 한꺼번에 다 지워야 하며, 삭제후 절대 되돌릴 수 없습니다.

4. Truncate table역시 테이블 내 행들을 삭제하지만 삭제되는 각 행을 기록하지 않고 대신 테이블의 데이터베이스 할당 해제를 기록하여 작업이 빠릅니다. TRUNCATE TABLE은 롤백 할 수 없습니다.

 

5. DROP명령어는 테이블 전체를 삭제, 공간, 객체를 삭제합니다. 삭제 후 되돌릴 수 없습니다.

 

Q. WHERE절과 HAVING절의 다른 점은 무엇입니까?

A. Having절은 그룹함수의 그룹의 조건으로 사용되고, where절은 select할 데이터에 조건을 주는 역할을 합니다.

 

Q. 기본키(Primary Key)와 유일키 (Unique Key)의 차이점은 무엇입니까

A. 기본키는 널을 허용하지 않지만 유일키는 모든 컬럼 중 유일하게 하나에 대한 NULL을 허용합니다. 그래서 UNIQUE키는 개체 하나하나를 구분할 기본키가 될 수 없습니다.

 

Q. 쿼리 순서

A. SELECT -> FROM -> WHERE -> GROUP BY -> ORDER BY

 

참고사이트

https://sas-study.tistory.com/56

반응형

'2020 > 신입 개발자 면접 질문 모음' 카테고리의 다른 글

신입개발자 면접 질문 #JSP  (0) 2020.03.16
신입개발자 기술면접 #Spring framework  (0) 2020.03.16
iBatis 란  (0) 2020.03.15
DI 와 AOP의 대해 설명하시오.  (0) 2020.03.12
면접 질문 spring  (0) 2020.03.12
블로그 이미지

꽃꽂이하는개발자

,
반응형

1. Java에서 DataBase를 편하게 Handling 할 수 있게 해주는 프ㅔ임 워크

2. 특징 : 

  • SQL문과 Java코드와의 분리 만으로도 Java개발자는 Query문을 신경쓰지 않아도 됨. SQL문이 변경되더라도 파라미터 값만 변경 되지 않는 다면 Java소스에서 수정할 부분이 없기 때문.

3. MVC 모델에서 커버하는 부분 : Model 지원

4. 실행 순서(실행 구조) : 

  • 자바 코드 내에서 특정 궈리문을 실행하기 원할 때, 파라미터아 필요한 조건을 넘기기 위한 객체를 생성
  • SQLMaps를 실행하기 위해 쿼리의 객체와 이름을 넘겨줌.
  • 쿼리가 실행되었을 때 SQLMaps는 쿼리 결과를 받기 위해 정의 된 클래스의 인스턴스를 생성하게 됨
  • 인스턴스는 데이터베이스에 의해 반환 된 ResultSet으로부터 만들어짐.
  •  
반응형
블로그 이미지

꽃꽂이하는개발자

,
반응형

To do List.

1. Client GUI Design

 

Chat Client 프로젝트의 Main 클래스

package application;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import javafx.application.Application;
import javafx.application.Platform;
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.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;

public class Main extends Application {

	Socket socket;
	TextArea textArea;

	// 클라이언트 프로그램 동작 메소드 (어떤 IP로 , 어떤 port로 접속할지 정해줌)
	public void startClient(String IP, int port) {
		// 스레드 객체 생성!
		Thread thread = new Thread() {
			public void run() {
				try {
					// socket 초기화
					socket = new Socket(IP, port);
					receive();
				} catch (Exception e) {
					// 오류가 생긴다면
					if (!socket.isClosed()) {
						stopClient();
						System.out.println("[서버 접속 실패]");
						Platform.exit();
					}
				}
			}
		};
		thread.start();
	}

	// 클라이언트 프로그램 종료 메소드
	public void stopClient() {
		try {
			if(socket != null && !socket.isClosed()) {
				socket.close(); 
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	// 서버로부터 메시지를 전달받는 메소드
	public void receive() {
		// 서버 프로그램으로부터 메시지를 계속 전달 받을 수 있도록
		while (true) {
			try {
				// 서버로부터 메시지를 전달 받을 수 있도록
				InputStream in = socket.getInputStream();
				byte[] buffer = new byte[512];
				int length = in.read(buffer);
				if (length == -1)
					throw new IOException();
				String message = new String(buffer, 0, length, "UTF-8");
				Platform.runLater(() -> {
					// textArea는 GUI요소중 하나로 화면에 어떠한 메시지를 주고 받았는지 출력해 주는 요소.
					textArea.appendText(message);
				});

			} catch (Exception e) {
				stopClient();
				break;
			}
		}
	}

	// 서버로 메시지를 전송하는 메소드
	public void send(String message) {
		Thread thread = new Thread() {
			public void run() {
				try {
					OutputStream out = socket.getOutputStream();
					byte[] buffer = message.getBytes("UTF-8");
					out.write(buffer);
					out.flush();
				} catch (Exception e) {
					stopClient();
				}
			}
		};
		thread.start();
	}

	// 실제로 프로그램을 동작시키는 메서드
	@Override
	public void start(Stage primaryStage) {
		BorderPane root = new BorderPane();
		root.setPadding(new Insets(5));
		
		HBox hbox = new HBox();
		hbox.setSpacing(5);
		
		TextField userName = new TextField();
		userName.setPrefWidth(150);
		userName.setPromptText("닉네임을 입력하세요.");
		HBox.setHgrow(userName, Priority.ALWAYS);
		
		//서버에 ip주소가 들어갈 수 있도록.
		TextField IPText = new TextField("127.0.0.1");
		TextField portText = new TextField("9876");
		portText.setPrefWidth(80);
		
		hbox.getChildren().addAll(userName, IPText, portText);
		root.setTop(hbox);
		
		textArea = new TextArea();
		textArea.setEditable(false);
		root.setCenter(textArea);
		
		TextField input = new TextField();
		input.setPrefWidth(Double.MAX_VALUE);
		input.setDisable(true);
		
		input.setOnAction(event -> {
			send(userName.getText() + ": " + input.getText() + "\n");
			input.setText("");
			input.requestFocus();
		});
		Button sendButton = new Button("보내기");
		sendButton.setDisable(true);
		
		sendButton.setOnAction(event ->{
			send(userName.getText() + " : " + input.getText() + "\n");
			input.setText("");
			input.requestFocus();
		});
		Button connectionButton = new Button("접속하기");
		connectionButton.setOnAction(event -> {
			if(connectionButton.getText().equals("접속하기")) {
				int port = 9876;
				try {
					port = Integer.parseInt(portText.getText());
				}catch(Exception e) {
					e.printStackTrace();
				}
				startClient(IPText.getText(), port);
				Platform.runLater(() -> {
					textArea.appendText("[채팅방접속]\n");
				});
				connectionButton.setText("종료하기");
				input.setDisable(false);
				input.requestFocus();
				
			}else {
				stopClient();
				Platform.runLater(() ->{
					textArea.appendText("[채팅방 퇴장]");
				});
				connectionButton.setText("접속하기");
				input.setDisable(true);
				sendButton.setDisable(true);
			}
		});
		BorderPane pane = new BorderPane();
		pane.setLeft(connectionButton);
		pane.setCenter(input);
		pane.setRight(sendButton);
		
		root.setBottom(pane);
		Scene scene = new Scene(root, 500, 500);
		primaryStage.setTitle(" [채팅 클라이언트] ");
		primaryStage.setScene(scene);
		primaryStage.setOnCloseRequest(event -> stopClient());
		primaryStage.show();
		
		connectionButton.requestFocus();
		
	}

	// 프로그램의 진입점.
	public static void main(String[] args) {
		launch(args);
	}
}

chat server 프로젝트에서 Main 을 실행하고

chat client 프로젝트에서 Main을 실행합니다.

server 에서 접속하기를 누른후

client 여러개를 실행하여 접속하기를 누릅니다.

그러면 접속이 되고 실시간으로 채팅을 주고 받을 수 있습니다.

 

반응형
블로그 이미지

꽃꽂이하는개발자

,
반응형

클라이언트 기능 모듈 개발하기!

1. 채팅 서버를 만든 것 처럼 이클립스에서 new -> other -> javaFx검색 -> javaFxProject를 만듭니다.

2. Main class를 작성합니다.

package application;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;

public class Main extends Application {

	Socket socket;
	TextArea textArea;

	// 클라이언트 프로그램 동작 메소드 (어떤 IP로 , 어떤 port로 접속할지 정해줌)
	public void startClient(String IP, int port) {
		// 스레드 객체 생성!
		Thread thread = new Thread() {
			public void run() {
				try {
					// socket 초기화
					socket = new Socket(IP, port);
					receive();
				} catch (Exception e) {
					// 오류가 생긴다면
					if (!socket.isClosed()) {
						stopClient();
						System.out.println("[서버 접속 실패]");
						Platform.exit();
					}
				}
			}
		};
		thread.start();
	}

	// 클라이언트 프로그램 종료 메소드
	public void stopClient() {
		try {
			if(socket != null && !socket.isClosed()) {
				socket.close(); 
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	// 서버로부터 메시지를 전달받는 메소드
	public void receive() {
		// 서버 프로그램으로부터 메시지를 계속 전달 받을 수 있도록
		while (true) {
			try {
				// 서버로부터 메시지를 전달 받을 수 있도록
				InputStream in = socket.getInputStream();
				byte[] buffer = new byte[512];
				int length = in.read(buffer);
				if (length == -1)
					throw new IOException();
				String message = new String(buffer, 0, length, "UTF-8");
				Platform.runLater(() -> {
					// textArea는 GUI요소중 하나로 화면에 어떠한 메시지를 주고 받았는지 출력해 주는 요소.
					textArea.appendText(message);
				});

			} catch (Exception e) {
				stopClient();
				break;
			}
		}
	}

	// 서버로 메시지를 전송하는 메소드
	public void send(String message) {
		Thread thread = new Thread() {
			public void run() {
				try {
					OutputStream out = socket.getOutputStream();
					byte[] buffer = message.getBytes("UTF-8");
					out.write(buffer);
					out.flush();
				} catch (Exception e) {
					stopClient();
				}
			}
		};
		thread.start();
	}

	// 실제로 프로그램을 동작시키는 메서드
	@Override
	public void start(Stage primaryStage) {
	}

	// 프로그램의 진입점.
	public static void main(String[] args) {
		launch(args);
	}
}
반응형
블로그 이미지

꽃꽂이하는개발자

,
반응형

서버 GUI 디자인 작업하기

package application;
	
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javafx.application.Application;
import javafx.application.Platform;
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.text.Font;
import javafx.stage.Stage;


public class Main extends Application {
	
	//스레드 풀 사용(한정된 자원으로 안정적이게 서버를 운용하기 위해서 threadPool 기법을 사용합니다.)
	public static ExecutorService threadPool;
	//접속한 클라이언트들을 관리 할수 있도록 만듬.
	public static Vector<Client> clients = new Vector<Client>();
	//서버 소켓 생성
	ServerSocket serverSocket;
	//서버를 구동시켜 클라이언트의 연결을 기다리는 메소드.
	public void startServer(String IP, int port) {
		try {
			serverSocket = new ServerSocket();
			//특정한 ip번호와 port번호로 특정한 클라이언트에게 접속을 기다리게 해줌
			serverSocket.bind(new InetSocketAddress(IP, port));
		}catch(Exception e) {
			e.printStackTrace();
			//서버 소켓이 닫혀있는 경우가 아니라면 
			if(!serverSocket.isClosed()) {
				stopServer();//서버를 종료
			}
			return;
		}
		// 클라이언트가 접속할 때 까지 계속 기다리는 스레드.
		Runnable thread = new Runnable() {

			@Override
			public void run() {
				//계속해서 새로운 클라이언트가 접속 할 수 있도록 해줌
				while(true) {
					try {
						Socket socket = serverSocket.accept();
						clients.add(new Client(socket));
						System.out.println(" [클라이언트 접속] "
								+ socket.getRemoteSocketAddress()
								+ " :" + Thread.currentThread().getName());
					}catch(Exception e) {
						//   서버 소켓에 문제가 생긴거니 서버를 종료 시키고 break문을 활용해서 빠져나갑니다.
						if(!serverSocket.isClosed()) {
							stopServer();
						}
						break;
					}
				}
			}
			
		};
		//스레드 풀을 초기화
		threadPool = Executors.newCachedThreadPool();
		//클라이언트에 접속을 원하는 스레드를 넣어줍니다. 
		threadPool.submit(thread);
	}
	//서버의 작동을 중지시켜주는 메소드
	public void stopServer() {
		try {
			//현재 작업중인 모든 소켓 닫기
			Iterator<Client> iterator = clients.iterator();
			//한명 한명의 클라이언트에게 접근
			while(iterator.hasNext()) {
				Client client = iterator.next();
				client.socket.close();
				iterator.remove();
			}
			//서버 소켓 객체 닫기
			if(serverSocket != null && !serverSocket.isClosed()) {
				serverSocket.close();
				
			}
			//스레드풀 종료
			if(threadPool != null && !threadPool.isShutdown()) {
				threadPool.shutdown();
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	//UI를 생성하고 , 실질적으로 프로그램을 동작시키는 메서드
	@Override
	public void start(Stage primaryStage) {
		//하나의 전체 디자인 틀을 담을 수 있는 하나의 펜을 생성 
		BorderPane root = new BorderPane();
		//내부 페이딩 5
		root.setPadding(new Insets(5));
		
		TextArea textArea = new TextArea();
		textArea.setEditable(false);
		textArea.setFont(new Font("나눔고딕", 15));
		root.setCenter(textArea);
		
		//토글 버튼은 스위치라고 생각하시면 됨.
		Button toggleButton = new Button("시작하기");
		toggleButton.setMaxWidth(Double.MAX_VALUE);
		BorderPane.setMargin(toggleButton, new Insets(1, 0, 0, 0));
		root.setBottom(toggleButton);
		
		//자신의 로컬 서버
		String IP = "127.0.0.1";
		int port = 9876;
		
		toggleButton.setOnAction(event -> {
			if(toggleButton.getText().equals("시작하기")) {
				startServer(IP, port);
				//자바 fx같은 경우는 바로 textArea에 쓰면 안되고 runLator와 같은 함수를 이용하여 어떠한 gui요소를 출력할 수 있도록 해야함.
				Platform.runLater(() -> {
					String message = String.format("[서버 시작]\n", IP, port);
					textArea.appendText(message);
					toggleButton.setText("종료하기");
				});
			}else {
				stopServer();
				Platform.runLater(() -> {
					String message = String.format("[서버 종료]\n", IP, port);
					textArea.appendText(message);
					toggleButton.setText("시작하기");
				});
			}
		});
		//크기
		Scene scene = new Scene(root, 500, 500);
		primaryStage.setTitle("[ 채팅 서버 ]");
		primaryStage.setOnCloseRequest(event -> stopServer());
		primaryStage.setScene(scene);
		primaryStage.show();
	}
	
	
	
	//프로그램의 메인 메서드
	public static void main(String[] args) {
		launch(args);
	}
}

public void start 함수 작성함

# 모든 import 는 javafx로 합니다.

# 혹시 아래와 같은 에러가 뜨신다면 글 확인해주세요.

2020/03/15 - [IT Q_A] - java.net.BindException: Cannot assign requested address: JVM_Bind

 

반응형
블로그 이미지

꽃꽂이하는개발자

,
반응형

C:\Windows\System32\drivers\etc에 있는 hosts파일에 저장되어 있는 local ip와 현재 ip가 달라서 발생하는 오류입니다.
저같은 경우는 hosts를 visual code로 열어서

ip주소를 맞춰주었더니 해결이 되었습니다.

(기존 ip 주소는 127.0.0.0으로 되어 있었음.. 127.0.0.1로 바꾸니 해결됬어요)

반응형
블로그 이미지

꽃꽂이하는개발자

,
반응형

Client 클래스

package application;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

//한명의 클라이언트와 통신하게 해주는 클래스 입니다.
public class Client {
	
		//소켓이 있어야지 클라이언트와 네트워크상에서 통신할 수 있음.
		Socket socket;
		
		//생성자 생성
		public Client(Socket socket) {
			this.socket = socket;
			
			//반복적으로 클라이언트로부터 메시지를 전달받을 수 있도록 receive()함수를 만듬.
			receive();
		}
		
		//클라이언트로부터 메시지를 전달받는 메소드.
		public void receive() {
			//작업 생성은 Runnable 인터페이스 or Callable 인터페이스를 구현한 클래스로 작업요청할 코드를 삽입해 작업을 만들 수 있습니다.
			//둘의 차이점은 Runnable의 run() 메서드는 리턴값이 없고, Callable의 call() 메서드는 리턴 값이 있습니다.
			Runnable thread = new Runnable() {
				@Override
				public void run() {
					try {
						//반복적으로 클라이언드에게 내용을 받을 수 있도록  while문 생성
						while(true) {
							//어떤 내용을 전달 받을 수 있도록 inputstream객체 사용
							InputStream in = socket.getInputStream();
							//버퍼를 사용해서 한번에 512byte까지 받을 수 있도록 설정
							byte[] buffer = new byte[512];
							//메시지의 크기
							int length = in.read(buffer);
							while(length == -1) throw new IOException();
							//서버에 접속을 한 클라이언트의 주소정보 출력, 스레드의 이름값을 출력, 
							System.out.println("[메시지 수신 성공]"
									+ socket.getRemoteSocketAddress()
									+ ":" + Thread.currentThread().getName());
							//전달받은 값을 한글도 포함 할 수 있도록 UTF-8 설정
							String message = new String(buffer, 0, length, "UTF-8");
							//전달받은 메시지를 다른 클라이언트들에게 보낼 수 있도록 만들어 줍니다.
							for(Client client : Main.clients) {
								client.send(message);
							}
						}
						
					}catch(Exception e){
						try {
							System.out.println(" [메시지 수신 오류]"
							+ socket.getRemoteSocketAddress()
							+ " : " + Thread.currentThread().getName());
						}catch(Exception e2){
							e2.printStackTrace();
						}
					}
				}
				
			};
			//메인함수에 있는 스레드풀에 섭밋을 해줍니다.
			//즉 스레드풀에 만들어진 하나의 스레드를 등록
			Main.threadPool.submit(thread);
		}
		
		//클라이언트에게 메시지를 전송하는 메소드.
		public void send(String message) {
			Runnable thread = new Runnable() {

				@Override
				public void run() {
					try {
						OutputStream out = socket.getOutputStream();
						byte[] buffer = message.getBytes("UTF-8");
						//버퍼에 담긴 내용을 서버에서 클라이언트에게 전송
						out.write(buffer);
						out.flush();
					}catch(Exception e){
						try {
							System.out.println("[메시지 송수신 오류]" 
									+ socket.getRemoteSocketAddress()
									+ " :" + Thread.currentThread().getName());
								Main.clients.remove(Client.this);
								socket.close();
						}catch(Exception e2) {
							e2.printStackTrace();
						}
					}
					
				}
				
			};
			Main.threadPool.submit(thread);
		}
		
}

Main class

package application;
	
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

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


public class Main extends Application {
	
	//스레드 풀 사용(한정된 자원으로 안정적이게 서버를 운용하기 위해서 threadPool 기법을 사용합니다.)
	public static ExecutorService threadPool;
	//접속한 클라이언트들을 관리 할수 있도록 만듬.
	public static Vector<Client> clients = new Vector<Client>();
	//서버 소켓 생성
	ServerSocket serverSocket;
	//서버를 구동시켜 클라이언트의 연결을 기다리는 메소드.
	public void startServer(String IP, int port) {
		try {
			serverSocket = new ServerSocket();
			//특정한 ip번호와 port번호로 특정한 클라이언트에게 접속을 기다리게 해줌
			serverSocket.bind(new InetSocketAddress(IP, port));
		}catch(Exception e) {
			e.printStackTrace();
			//서버 소켓이 닫혀있는 경우가 아니라면 
			if(!serverSocket.isClosed()) {
				stopServer();//서버를 종료
			}
			return;
		}
		// 클라이언트가 접속할 때 까지 계속 기다리는 스레드.
		Runnable thread = new Runnable() {

			@Override
			public void run() {
				//계속해서 새로운 클라이언트가 접속 할 수 있도록 해줌
				while(true) {
					try {
						Socket socket = serverSocket.accept();
						clients.add(new Client(socket));
						System.out.println(" [클라이언트 접속] "
								+ socket.getRemoteSocketAddress()
								+ " :" + Thread.currentThread().getName());
					}catch(Exception e) {
						//   서버 소켓에 문제가 생긴거니 서버를 종료 시키고 break문을 활용해서 빠져나갑니다.
						if(!serverSocket.isClosed()) {
							stopServer();
						}
						break;
					}
				}
			}
			
		};
		//스레드 풀을 초기화
		threadPool = Executors.newCachedThreadPool();
		//클라이언트에 접속을 원하는 스레드를 넣어줍니다. 
		threadPool.submit(thread);
	}
	//서버의 작동을 중지시켜주는 메소드
	public void stopServer() {
		try {
			//현재 작업중인 모든 소켓 닫기
			Iterator<Client> iterator = clients.iterator();
			//한명 한명의 클라이언트에게 접근
			while(iterator.hasNext()) {
				Client client = iterator.next();
				client.socket.close();
				iterator.remove();
			}
			//서버 소켓 객체 닫기
			if(serverSocket != null && !serverSocket.isClosed()) {
				serverSocket.close();
				
			}
			//스레드풀 종료
			if(threadPool != null && !threadPool.isShutdown()) {
				threadPool.shutdown();
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	//UI를 생성하고 , 실질적으로 프로그램을 동작시키는 메서드
	@Override
	public void start(Stage primaryStage) {
	}
	
	//프로그램의 메인 메서드
	public static void main(String[] args) {
		launch(args);
	}
}

 

다음 글에서 계속 하겠습니다.

반응형
블로그 이미지

꽃꽂이하는개발자

,
반응형

 

1. 자신의 운영체제에 맞는 Java FX Scene Buler을 설치해 줍니다.

https://www.oracle.com/java/technologies/javafxscenebuilder-1x-archive-downloads.html

 

JavaFX Scene Builder 1.x Archive

No results found Your search did not match any results. We suggest you try the following to help find what you're looking for: Check the spelling of your keyword search. Use synonyms for the keyword you typed, for example, try “application” instead of “sof

www.oracle.com

2. eclipse의 help -> Market Place -> java fx 검색후 설치를 해줍니다.

 

3.  이제 프로젝트를 만들어 줍니다. 마우스 오른쪽 클릭해서 new-> other ->javafx검색->JavaFX Project생성

저는 Chat Server 이란 이름으로 만들어 주었습니다.

그 후에 application 패키지 내에 Client라는 Class를 생성해 주겠습니다.

Client 클래스

package application;

import java.net.Socket;

//한명의 클라이언트와 통신하게 해주는 클래스 입니다.
public class Client {
	
		//소켓이 있어야지 클라이언트와 네트워크상에서 통신할 수 있음.
		Socket socket;
		
		//생성자 생성
		public Client(Socket socket) {
			this.socket = socket;
			
			//반복적으로 클라이언트로부터 메시지를 전달받을 수 있도록 receive()함수를 만듬.
			receive();
		}
		
		//클라이언트로부터 메시지를 전달받는 메소드.
		public void receive() {
			
		}
		
		//클라이언트에게 메시지를 전송하는 메소드.
		public void send(String message) {
			
		}
		
}

 

다음으로 Main class로 가서 입력해 줍니다.

package application;
	
import java.net.ServerSocket;
import java.util.Vector;
import java.util.concurrent.ExecutorService;

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


public class Main extends Application {
	
	//스레드 풀 사용(한정된 자원으로 안정적이게 서버를 운용하기 위해서 threadPool 기법을 사용합니다.)
	public static ExecutorService threadPool;
	//접속한 클라이언트들을 관리 할수 있도록 만듬.
	public static Vector<Client> client = new Vector<Client>();
	//서버 소켓 생성
	ServerSocket serverSocekt;
	//서버를 구동시켜 클라이언트의 연결을 기다리는 메소드.
	public void startServer(String IP, int port) {
		
	}
	//서버의 작동을 중지시켜주는 메소드
	public void stopServer() {
		
	}
	
	//UI를 생성하고 , 실질적으로 프로그램을 동작시키는 메서드
	@Override
	public void start(Stage primaryStage) {
	}
	
	//프로그램의 메인 메서드
	public static void main(String[] args) {
		launch(args);
	}
}

 

기본적인 함수들을 만들어 주었습니다.

다음 글로 넘어가겠습니다.

 

반응형
블로그 이미지

꽃꽂이하는개발자

,