반응형
<a href="http://www.google.co.kr" target="_self"> 현재 출력되고 있는 페이지에 google 띄우기</a>

<a href="http://www.google.co.kr" target="_blank">새로운 창에 google 띄우기</a>

기본적으로 target은 _self로 설정되어 있으며 target="_blank"를 통하여 새로운창에 링크를 띄울 수 있습니다.

 

반응형

'2020 > HTML' 카테고리의 다른 글

<progress> 태그  (0) 2020.03.20
<html> 위 첨자, 아래 첨자  (0) 2020.03.19
<mark> <em>  (0) 2020.03.19
HTML 약어 설정하기 <abbr>  (0) 2020.03.19
블로그 이미지

꽃꽂이하는개발자

,
반응형

Q. Servelt, JSP

A.

Servlet - Container가 이해할 수 있도록 구성된 자바코드로 이루어진 Html in JAVA

JSP(Java Server Page) - Html기반에 자바코드를 블록화하여 삽입한 것(JAVA in Html)

 

Q. Get과 Post차이

A. 

1. GET방식

  • 클라이언트에서 서버로 데이터를 전달할 때, 주소 뒤에 "이름"과 "값"이 결합된 쿼리 스트링 형태로 전달
  • 주소창에 쿼리 스트링이 그대로 보여지기 때문에 보안성이 떨어진다.
  • 길이에 제한이 있다.
  • Post방식보다 상대적으로 전송 속도가 빠르다.

2.POST방식

  • 일정 크기 이상의 데이터를 보내야 할 때 사용한다.
  • 서버로 보내기 전에 인코딩하고, 전송 후 서버에서는 다시 디코딩 작업을 한다.
  • 주소창에 전송하는 데이터의 정보가 노출되지 않아 Get방식에 비해 보안성이 높다.
  • 속도가 Get방식보다 느리다.
  • 쿼리 스트링(문자열)데이터 뿐만 아니라. 라디오 버튼, 텍스트 박스 같은 객체들의 값도 전송이 가능하다.

3. GET, POST차이

  • Get은 주로 웹 브라우저가 웹 서버에 데이터를 요청할 때 사용
  • Post는 웹 브라우저가 웹 서버에 데이터를 전달하기 위해 사용
  • GET을 사용하면 웹 브라우저에서 웹 서버로 전달되는 데이터가 인코딩되어 URL에 붙는다.
  • POST방식은 전달되는 데이터가 보이지 않는다
  • GET방식은 전달되는 데이터가 255개의 문자를 초과하면 문제가 발생할 수 있다.
  • 웹 서버에 많은 데이터를 전달하기 위해서는 POST방식을 사용하는 것이 바람직하다.

Q. Session가 Cookie

A.

1. Session과 Cookie 사용이유

  현재 우리가 인터넷에서 사용하고 있는 HTTP 프로토콜은 연결 지향적인 성격을 버렸기 때문에 새로운 페이지를 요청할 때마다 새로운 접속이 이루어지며 이전 페이지와 현재 페이지 간의 관계가 지속되지 않는다. 이에 따라 HTTP프로토콜을 이용하게 되는 웹사이트에서는 웹페이지에 특정 방문자가 머무르고 있는 동안에 그 방문자의 상태를 지속시키기 위해 쿠키와 세션을 이용한다.

 

2. Session

  • 특정 웹사이트에서 사용자가 머무르는 기간 또는 한 명의 사용자의 한번의 방문을 의미한다.
  • Session에 관련된 데이터는 Server에 저장된다.
  • 웹 브라우저의 캐시에 저장되어 브라우저가 닫히거나 서버에서 삭제시 사라진다.
  • Cokkie에 비해 보안성이 좋다.

3. Cookie

  • 사용자의 정보를 유지할 수 없다는 HTTP의 한계를 극복할 수 있는 방법
  • 인터넷 웹 사이트의 방문 기록을 남겨 사용자와 웹사이트 사이를 매개해주는 정보이다.
  • Cookie는 인터넷 사용자가 특정 웹서버에 접속할 때, 생성되는 개인 아이디와 비밀번호, 방문한 사이트의 정보를 담은 임시파일로써, Server가 아닌 Client에 텍스트 파일로 저장되어 다음에 해당 웹서버를 찾을 경우 웹서버에서는 그가 누구인지 어떤 정보를 주로 찾았는지 등을 파악할 때 사용된다.
  • Cookie는 Client PC에 저장되는 정보이기 때문에, 다른 사용자에 의해서 임의로 변경이 가능하다.

Q. 보안성이 낮은 Cookie대신 Session을 사용하면 되는데 안하는 이유?

A. 모든 정보를 Session에 저장하면 Server의 메모리를 과도하게 사용하게 되어 Server에 무리가 가게된다.

 

Q. MVC패턴

A.

1. MVC?

  • 객체지향프로그래밍에서, MVC란 사용자 인터페이스를 성공적이며 효과적으로 데이터 모형에 관련 시키기 위한 방법론 또는 설계 방식중 하나이다. MVC방식은 자바 Smalltalk
  • MVC패턴은 목적 코드의 재사용에 유용한 것은 물론, 사용자 인터페이스와 응용프로그램 개발에 소요되는 현저하게 줄여주는 형식이라고 많은 개발자들이 평가

2.MVC 구성요소

  • Model - 소프트웨어 응용과 그와 관련된 고급 클래스 내의 논리적 데이터 기반 구조를 표현, 이 목적 모형은 사용자 인터페이스에 관한 어떠한 정보도 가지고 있지 않다.
  • View - 사용자 인터페이스 내의 구성요소들을 표현(사용자에게 보여지는 화면)
  • Controller - Model과 View를 연결하고 있는 클래스를 대표, Model과 View 내의 클래스들 간의 정보교환 하는데 사용
반응형
블로그 이미지

꽃꽂이하는개발자

,
반응형

1. Framework

  • 특정 형태의 소프트웨어 문제를 해결하기 위해 상호 협력하는 클래스 프레임과 인터페이스 프레임의 집합
  • 특정한 틀을 만들어 놓고 거기에 내가 만든 부품을 조립하여 작업시간을 줄여주는 것
  • 특정 개념들의 추상화를 제공하는 여러 클래스나 컴포넌트로 구성
  • 추상적인 개념들이 문제를 해결하기 위해 같이 작업하는 방법을 정의
  • 프레임워크는 좀 더 높은 수준에서 패턴을 조작
  • 프레임워크가 중요한 이유는 객체지향 개발을 하게 되면서 개발자의 취향에 따라 다양한 프로그램이 나오게 되었다. 프로그램 개발에 투입되는 개발자도 점점 늘어남에 따라 전체 시스템의 통합성, 일관성이 부족하게 되었기 때문이다. 그래서 개발자의 자유를 제한하기 위해 프레임워크를 도입했다.

 

  • 프레임워크가 가져야 할 특징
  • - 개발자들이 따라야할 가이드라인을 가진다
  • - 개발할 수 있는 범위가 정해져 있다.
  • - 개발자를 위한 다양한 도구들이 지원된다.

 

  • 프레임워크의 장단점
  • 장점 - 개발 시간을 줄일 수 있고 오류로부터 자유로울 수 있다.
  • 단점 - 프레임워크에 너무 의존하면 개발 능력이 떨어져서 프레임워크 없이 개발하는 것이 불가능해진다.

 

2. Spring Framework(스프링 프레임워크)

  • 자바(JAVA)플랫폼을 위한 오픈소스 애플리케이션 프레임워크이다.
  • 자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크
  • 자바 개발을 위한 프레임워크로 종속 객체를 생성해주고, 조립해주는 도구
  • 자바로 된 프레임워크로 자바 SE로 된 자바 객체(POJO)를 자바 EE에 의존적이지 않게 연결해주는 역할

3. 스프링의 특징

  • 가볍다
  • 제어 역행(IoC)이라는 기술을 통해 애플리케이션의 느슨한 결합을 도모
  • 관점 지향 프로그래밍(AOP)을 위한 풍부한 자원
  • 애플리케이션 객체의 생명주기와 설정을 포함하고 관리한다는 점에서 일종의 컨테이너(Container)라고 할 수 있다.
  • 간단한 컴포넌트로 복잡한 애플리케이션을 구성하고 설정할 수 있다.

4. 스프링의 특징

  • 경량 컨테이너로써 자바 객체를 직접 관리한다. 각각의 객체 생성, 소멸가 같은 라이프 사이클을 관리하며 스프링으로부터 필요한 객체를 얻어 올 수 있다.
  • 스프링은 POJO(Plain Old Java Object)방식의 프레임워크이다. 일반적인 J2EE 프레임워크에 비해 구현을 위하여 특정한 인터페이스를 구현하거나 상속을 받을 필요가 없어 기존에 존재하는 라이브러리등을 지원하기에 용이하고 객체가 가볍다.
  • 스프링은 제어의 역행(IoC : Inversion of Control)을 지원한다. 컨트롤의 제어권이 사용자가 아니라 프레임워크에 있어서 필요에 따라 스프링에서 사용자의 코드를 호출한다.
  • 스프링은 의존성 주입(DI: Dependency Injection)을 지원한다. 각각의 계층이나 서비스들 간에 의존성이 존재할 경우 프레임워크가 서로 연결시켜준다.
  • 스프링은 관점 지향 프로그래밍(AOP: Aspect-Oriented Programming)을 지원한다. 따라서 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리할 수 있다.
  • 스프링은 영속성과 관련된 다양한 서비스를 지원한다. MyBatis나 Hibernate등 이미 완성도가 높은 데이터베이스 처리 ㄱ라이브러이와 연결할 수 있는 인터페이스를 제공한다.
  • 스프링은 확장성이 높다. 스프링 프레임워크에 통합하기 위해 간단하게 기존 라이브러리를 감싸는 정도로 스프링에서 사용이 가능하기 때문에 수많은 라이브러리가 이미 스프링에서 지원되고 있고 스프링에서 사용되는 라이브러리를 별도로 분리하기도 용이하다.

5. Spring MVC 구조의 처리과정

  • DispatcherServlet: 어플리케이션으로 들어오는 모든 Request를 받는 관문이다. Request를 실제로 처리할 Controller에게 전달하고 그 결과값을 받아서 View에게 전달하여 적절한 응답을 생성할 수 있도록 흐름을 제어한다.
  • HandleMapping: Request URL 각각 어떤 Controller가 실제로 처리할 것인지 찾아주는 역할
  • Controller: Request를 직접 처리한 후 그 결과를 다시 DispatcherServlet에게 돌려준다.
  • ModelAndView: Controller가 처리한 결과와 그 결과를 보여줄 View에 관한 정보를 담고있는 객체이다.
  • ViewResolver: View관련 정보를 갖고 실제 View를 찾아주는 역할을 한다.
  • View: Controller가 처리한 결과값을 보여줄 View를 생성한다.

참고 사이트

https://sas-study.tistory.com/58?category=774876

반응형
블로그 이미지

꽃꽂이하는개발자

,
반응형

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

 

반응형
블로그 이미지

꽃꽂이하는개발자

,