728x90
반응형

Array

  • 선언은 2가지 방식으로 할 수 있다.
int[] marks = {1,2,3,4,5};
int[] marks = new int[5];
  • java의 배열의 length는 속성이지, 메서드가 아니다.
marks.length
  • 배열의 요소들을 출력하고 싶다면, for문을 사용해서 인덱스마다 출력해도 되고, Arrays.toString(배열이름); 을 사용해도 된다. (배열의 콘텐츠 불러오기)
System.out.println("Arrays.toString(persons) = " + Arrays.toString(persons));
// Arrays.toString(marks) = [1, 2, 3, 4, 5]
  • 배열의 모든 값을 한번에 바꾸는 방법도 있다. Arrays.fill(배열이름, 바꾸고 싶은 값);
int[] marks2 = {100, 99, 95, 96, 100};
for (int mark : marks2) {
    System.out.println("mark = " + mark);
}

Arrays.fill(marks2, 100);
for (int mark : marks2) {
    System.out.println("mark = " + mark);
}
  • 두 배열이 같은 요소를 가지는지 확인할 수 있다. Arrays.equals(배열1, 배열2)
Arrays.equals(marks, marks2)
  • 배열 정렬 Arrays.sort(배열이름);
  • inline : 함수의 내용을 호출을 통해서 실행시키는 것이 아니라, 호출하는 코드 자체가 함수 내용의 코드가 된다.
int[] marks = {100, 90, 80, 20, 40};
Student student = new Student("김태헌", marks);
// inline
Student student = new Student("김태헌", new int[] {100, 90, 80, 20, 40});
  • 가변 변수를 인자로 입력받기 ( 배열의 크기가 다양할 때 사용하면 좋다 ) … 을 사용하면 된다. 가변 인수는 항상 메소드의 마지막에 와야 한다!
void print(int... values){
    System.out.println("Arrays.toString(values) = " + Arrays.toString(values));
}

student.print(1,2,3,4,5); // Arrays.toString(values) = [1, 2, 3, 4, 5]
student.print(1,2); // Arrays.toString(values) = [1, 2]

int sum(int... values) {
    int sum = 0;
    for (int value : values) {
        sum += value;
    }
    System.out.println("sum = " + sum);
    return sum;
}
student.sum(1,2,3,4,5,346,234,23,42,34,23,423); // sum = 1140
  • Array에 다른 요소 하나 추가하는 방법 → 배열 자체를 새로 만들어야 한다. (배열을 한 번 생성 했다면 이후에 요소의 개수를 변경할 방법은 없다)
  • Array에 요소를 지우고 싶은 경우에도 새로운 배열을 만들면 된다
  • 이 과정이 귀찮으므로 ArrayList에 있는 메서드를 사용하면 된다.

ArrayList

  • ArrayList는 다음과 같이 선언한다.
    add와 remove를 이용해서 추가하고 제거할 수 있다.
ArrayList arrayList = new ArrayList();
arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add(1); // String과 Int가 섞여서 들어갈 수 있다. 그치만 같은 자료형이 들어가는 것이 좋다.
System.out.println("arrayList = " + arrayList);
arrayList.remove("Apple");
System.out.println("arrayList = " + arrayList);
  • ArrayList에는 다양한 자료형이 들어가도 되지만 같은 자료형이 들어가는 것이 좋으므로, 미리 자료형을 선언한다. 그럼 다른 자료형이 들어가면 오류가 난다.
ArrayList<String> items = new ArrayList<>(); // 제네릭
728x90
반응형
728x90
반응형

데이터베이스 연동(1) - ORM, JPA, Hibernate, Mybatis, JDBC

ORM(Object Relational Mapping)

ORM은 Object Relational Mapping의 줄임말로 객체 관계 매핑을 의미한다. Java와 같은 객체지향 언어에서 의미하는 객체(클래스)와 RDB(Relational Database)의 테이블을 자동으로 연결(mapping)하는 방법이다.

 

클래스는 데이터베이스의 테이블과 연결(mapping)하기 위해 만들어진 것이 아니기 때문에 RDB 테이블과 어쩔 수 없는 불일치가 존재한다. ORM은 이 둘의 불일치와 제약사항을 해결하는 역할이다.

ORM의 장단점

ORM의 장점

  • ORM을 이용하면 쿼리문 작성이 아닌 코드(Method)로 데이터를 조작할 수 있어서 개발자는 객체 모델을 이용하여 비즈니스 로직으로 구성하는데만 집중할 수 있다.
    (물론 내부적으로는 쿼리를 생성하여 DB를 조작한다)
  • 연결하는 정보가 Class로 명시되어 있으면 ERD를 보는 의존도도 낮출 수 있다.
  • 재사용 및 유지보수가 편하다
  • 데이터베이스에 대한 종속성이 줄어든다. 예를 들어 DB를 MySQL에서 PostgreSQL로 변환한다면 쿼리를 새로 짜야되는데 ORM을 사용한다면 쿼리를 수정할 필요가 없다.

 

ORM의 단점

  • 복잡한 서비스의 경우 직접 쿼리를 구현하지 않고 코드로 구현하기 어렵다
  • 복잡한 쿼리를 정확한 설계 없이 ORM만으로 구성하게 되면 속도 저하 등의 성능 문제가 발생할 수 있다.
  • 프로젝트의 규모가 크고 복잡하여 설계가 잘못된 경우, 속도 저하 및 일관성을 무너뜨릴 수 있다.
  • 세분성 : ORM의 자동 설계 방법에 따라 데이터베이스에 있는 테이블의 수와 애플리케이션의 엔티티 클래스의 수가 다른 경우가 생긴다.
  • 상속성 : RDBMS에는 상속이라는 개념이 없다
  • 식별성 : RDBMS는 기본 키로 동일성을 정의하는데 자바는 두 객체의 값이 같아도 다르다고 판단할 수 있다
  • 연관성 : 객체 지향 언어는 객체를 참조함으로써 연관성을 나타내지만 RDBMS에서는 외래키를 삽입함으로써 연관성을 표현한다. 또한 객체지향 언어에서 객체를 참조할 때는 방향성이 존재하지만 RDBMS에서 외래키를 삽입하는 것은 양방향의 관계를 가지기 때문에 방향성이 없다.

JPA(Java Persistence API)

Java Persistence API는 자바 진영의 ORM 기술 표준으로 채택된 인터페이스의 모음이다. (Java에서 제공한다. 즉, ORM을 사용하기 위한 표준 인터페이스들을 모아둔 것이다)

 

이전에는 EJB, 엔티티 빈 이라는 개념들로 사용했는 이를 대체하기 위한 기술이 JPA이다.

 

JPA 또한 실제로 동작하는 것이 아니라 어떻게 동작해야 하는지 메커니즘을 정리한 표준 명세로 생각하면 된다. (즉, 인터페이스 이기 때문에 JPA를 구현하기 위해 Hibernate나 OpenJPA같은 프레임워크를 사용한다. JPA는 구현된 클래스와 연결해주기 위해 사용되는 프레임워크)

 

JPA의 메커니즘을 보면 내부적으로 JDBC를 사용한다. 개발자가 직접 JDBC를 구현하면 SQL에 의존하게 되는 문제 등이 있어 개발의 효율성이 떨어지는데, JPA는 이 같은 문제점을 보완해서 개발자 대신 적절한 SQL을 생성하고 데이터베이스를 조작해서 객체를 자동 매핑하는 역할을 수행한다.

 

ORM에서의 단점을 일부 해결하였는데, 데이터베이스는 상속관계를 지원하지 않는데 JPA는 이를 해결하였다.

예를 들어서 item이라는 table에 name과 price라는 column이 있다고 가정하자. 이를 상속하여서 나는 book이라는 table을 만들고 싶다면 item의 id를 book이 primary key로 상속받는 형식으로 해결한다.

 

JPA의 구성요소로는 javax.persistence 패키지로 정의된 API 그 자체가 있고, JPQL(Java Persistence Query Language) 그리고 객체관계 메타데이터로 구성된다고 한다.

 

JPA 기반의 구현체(ORM 프레임워크)는 대표적으로 세가지가 있다. (하이버네이트, 이클립스 링크, 데이터 뉴클리어스)

이 중에서도 하이버네이트를 제일 많이 사용한다.

하이버네이트

: 자바의 ORM 프레임워크로 JPA구현체 중 하나이다. Hibernate가 지원하는 메서드 내부에서는 JDBC API가 동작하고 있다.

 

HQL(Hibernate Query Language)이라 불리는 매우 강력한 쿼리 언어를 포함하고 있다.

 

HQL은 완전히 객체 지향적이며 상속, 다형성, 관계 등의 객체 지향의 강점을 사용할 수 있다.

 

HQL은 쿼리 결과로 객체를 반환하며 생성과 접근을 개발자가 원하는 대로 할 수 있다.

 

HQL은 페이지네이션과 동적 프로파일링 같은 기능을 제공한다고 한다.

 

JDBC(Java Database Connectivity)

JDBC는 DB에 접근할수 있도록 Java에서 제공하는 API이다. 모든 Java Data Access 기술의 근간이 되고, 모든 영속성컨텍스트의 프레임워크는 내부적으로 JDBC API를 사용한다고 보면된다.

 

Spring Data JPA

JPA를 편리하게 사용할 수 있도록 지원하는 스프링 하위 프로젝트 중 하나이다. 데이터베이스 CRUD 처리에 필요한 인터페이스를 제공하며, 하이버네이트의 엔티티 매니저를 직접 다루지 않고 리포지토리를 정의해 사용함으로써 스프링이 적합한 쿼리를 동적으로 생성하는 방식으로 데이터베이스를 조작한다. 이를 통해 하이버네이트에서 자주 사용되는 기능을 더 쉽게 사용할 수 있게 구현한 라이브러리이다.

 

Mybatis

ORM, JPA, Hibernate 이쪽과는 다른 방식으로 데이터베이스를 다룬다.

 

Mybatis는 SQL Mapper라는 개념을 사용하는 SQL Mapper는 자바 객체를 실제 SQL문에 연결해주어서 빠른 개발과 편리한 테스트 환경을 제공한다.

 

JDBC로 처리하는 부분 중 코드와 파라미터 설정 및 결과 연결(mapping)을 대신해준다.

(Mybatis의 예전 이름은 iBatis인데 Google Code로 이전되면서 이름이 바뀌었다.)

 

Mybatis vs JPA(ORM)

  • 영속 계층에서의 영속 프레임워크는 2개로 나눌 수 있는데 SQL Mapper와 ORM으로 나눌 수 있다.
  • ORM은 데이터베이스 객체를 자바 객체로 매핑함으로써 객체 간의 관계를 바탕으로 SQL을 자동으로 생성해준다.
    • 관계형 데이터베이스의 '관계'를 Object에 반영하자는 것이 목적이다
  • SQL Mapper는 SQL을 명시해주어야 한다.
  • JPA는 ORM 기술이고 MyBatis는 SQL Mapper의 한 종류이기 때문에 데이터베이스를 어떻게 다룰 것이냐에 따라 선택하면 될 것 같다

 

 

 

 

 

 

[참고] [JDBC] JDBC, JPA/Hibernate, Mybatis의 차이 - Heee's Development Blog

728x90
반응형
728x90
반응형

Gradle

Task들을 자동화 시켜 주는 Build Tool이다.

→ Task : Compile, Test, Packaging, Deploy, Run

안드로이드에서의 Task들은 다음과 같다.

Compile : Java나 Kotlin 파일을 바이트 코드로 변환해주는 작업

Test : 어플리케이션이 제대로 동작할지에 대한 Test를 하는 작업

Packaging : 코드를 패키징해 aab파일이나 apk 파일로 만들어주는것

Deploy & Run : 코드를 어플리케이션으로 패키징해서 실제 기기에 넣어서 실행할 수 있도록 만들어 주는 것.

스프링 → Compile과 Test는 안드로이드와 동일. 패키징은 jar나 war파일로 만들어준다.

Deploy&Run은 만들어진 스프링을 돌려 서버를 실행해주는 것을 뜻함.

장점

  1. 직관적인 코드와 자동완성
  2. 다양한 Repository 사용 가능
  3. 각 작업에 필요한 라이브러리들만을 가져오는 작업

implementation : 라이브러리를 가져오는 것을 뜻한다.

Groovy언어로도 사용할 수 있는데 Groovy는 자바 문법이랑 유사하고 Gradle Wrapper를 이용하면 Gradle이 설치되지 않은 시스템에서도 프로젝트를 빌드할 수 있다.

728x90
반응형
728x90
반응형

위와 같은 오류가 발생하였다.

 

발생한 상황은 다음과 같다.

게시판 서비스를 만드는데 게시글과 댓글을 mapping 해주기 위해서 댓글(article_comment)에 FK로 article_id 열을 넣어야 했다. 이 문제는 해당 SQL문을 실행할 때, article_id에 해당하는 게시물이 없어서 생기는 문제였다.

 

게시글의 id를 확인하여 존재하는 id를 넣어주면 된다. 

728x90
반응형
728x90
반응형

Channels and Buffers : 데이터는 항상 채널에서 버퍼로 읽히거나 버퍼에서 채널로 쓰여진다.

[Non-blocking IO]

하나의 Thread는 버퍼에 데이터를 읽도록 채널에 요청할 수 있다. 채널이 버퍼로 데이터를 읽는 동안 Thread는 다른 작업을 수행할 수 있다.

[Selectors]

selector는 여러 개의 채널에서 이벤트를 관리할 수 있는 객체이다.

[Channels]

channel에서 buffer로 읽거나 buffer를 채널로 쓰거나 할 수 있다.

( 이전에는 OutputStream과 InputStream을 사용하였어야 하는데 Channel만으로 할 수 있게 되었다)

channel에는 여러가지 type이 있다.

  • FileChannel : 파일에 데이터를 읽고 쓴다.
  • DatagramChannel : UDP를 이용해 네트워크를 통해 데이터를 읽고 쓴다.
  • SocketChannel : TCP를 이용해 네트워크를 통해 데이터를 읽고 쓴다.
  • ServerSocketChannel : 들어오는 TCP 연결을 수신할 수 있다. 들어오는 연결마다 SocketChannel이 만들어진다.

[Buffers ]

채널과 상호작용할 때 사용된다. 데이터는 채널에서 버퍼로 읽혀지거나, 버퍼에서 읽혀 채널로 쓰여진다.

  1. 버퍼에 데이터 쓰기
  2. buffer.flip() 호출 → 읽기모드
  3. 버퍼에서 데이터 읽기
  4. buffer.clear() 호출 → 쓰기 모드

Selectors : 셀렉터를 사용하면 하나의 쓰레드가 여러 채널을 처리할 수 있다.

Selector는 사용을 위해 하나 이상의 채널을 Selector에 등록하고 select() 메서드를 호출해 등록된 채널 중 이벤트 준비가 완료된 하나 이상의 채널이 생길 때까지 block된다.

Selector selector = Selector.open(); // Selector 생성

selector에 채널을 등록하기 위해서는 register() 메서드를 사용해야 한다. (채널을 selector에 등록)

channel.configureBlocking(false);
// selector에 채널을 등록하기 위해서는 반드시 해당 채널이 non-blocking 모드로 변환되어야 한다. 
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);

SelectionKey : register() 메서드를 이용해 채널을 Selector에 등록하면 SelectionKey 객체가 반환된다.

Channel channel = selectionKey.channel();
Selector selector = selectionKey.selector();

Selector에 하나 이상의 채널을 등록한 후에는 select() 메소드를 호출할 수 있다. select() 메소드는 accept, connect, read, write 이벤트에 대해 준비되어 있는 채널을 반환한다.

select()메서드를 사용하면 개수가 반환된다. select() 메서드를 통해 하나 이상의 준비된 채널이 발생하면, selectedKeys() 메서드를 사용해 준비된 채널의 집합을 반환 받는다.

Set<SelectionKey> selectedKeys = selector.selectedKeys();

[ServerSocketChannel] : ServerSocket과 마찬가지로 들어오는 TCP 연결을 수신 대기 할 수 있는 채널이다.

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
while(true){
	SocketChannel socketChannel = serverSocketChannel.accept();
}

ServerSocketChannel은 Non-blocking 모드로 설정이 가능하다.

SocketChannel은 TCP 네트워크 소켓에 연결된 채널이다. Socket의 역할과 같다.

SocketChannel도 non-blocking 모드로 설정할 수 있다.

728x90
반응형

'백엔드 > Network Programming' 카테고리의 다른 글

Socket Programming(3) - Socket for Server  (0) 2022.11.21
Socket Programming(2) - Socket for Client  (0) 2022.11.13
Socket Programming(1) - socket이란?  (0) 2022.11.13
URL and URI's key  (2) 2022.10.15
Internet protocols and layers  (2) 2022.09.09
728x90
반응형

ServerSocket Class

  • 서버쪽에서 Socket을 생성할 때도 ,hostname 또는 IP주소와 port number가 필요하다.
  • 서버의 입장에서는 누가 connection을 요청할지 알 수 가 없어서 binding된 port를 계속해서 듣고 있어야 한다
  • 그래서 Socket Class를 사용하지 않고 ServerSocket Class를 따로 만들어야 한다. 
  • Constructors
    • public ServerSocket(int port) throws BindException, IOException
    • public ServerSocket(int port, int queueLength) throws BindException, IOException
      • 서버는 동시에 여러 Client로부터 request를 받을 수 있기 때문에 동시에 처리를 못하니까 queue에다가 request를 넣어서 처리한다. queueLength는 queue의 길이를 의미한다.
    • public ServerSocket(int port, int queueLength, InetAddress bindAddress) throws IOException
    • public ServerSocket() throws IOException  => binding 없이 socket 생성하고 binding 반드시 해주어야 함
      • public void bind(SocketAddress endpoint) throws IOException
      • public void bind(SocketAddress endpoint, int queueLength) throws IOException

예를 들어 위와 같은 코드를 입력하면 지금 현재 내 컴퓨터에서 사용되고 있는 port number들을 보여준다.

엄청 많은 port가 사용되고 있는데 한번 64032번에서는 어떤 프로그램이 실행되고 있는지 확인해보자.

17352 PID에서 사용되고 있는 것을 알 수 있다. 그럼 작업 관리자에서 어떤 프로그램인지 확인할 수 있다.

KOSinj.exe(?) 이런게 port 64032에서 사용되고 있다는 사실을 알 수 있다.

 

Server Program의 life Cycle

  1. ServerSocket() 생성자를 통하여 특정 port에 ServerSocket이 생성된다
  2. ServerSocket은 들어오는 connection을 accept() 메서드를 통해 듣는다.
    • accept()는 blocking 형태로 동작한다 -> accept()가 connection이 올때까지 기다리고 밑에 라인은 실행하지 않는다. 
    • client와 server가 연결되면 Socket object를 리턴한다. ( client와 Server를 연결하는 소켓이다)
  3. Socket의 getInputStream()과 getOutputStream() 메서드를 호출할 수 있다.
  4. Server와 Client는 약속된 protocol에 따라 interact한다.
  5. Server, Client close connection
  6. 서버는 다음 connection을 위해 Step2로 가고 다음 connection을 기다린다.

DaytimeServer -> DaytimeClient를 실행하여 localhost의 port 13번에서 서버가 실행되는 것을 확인한다.

 

위의 코드의 문제점은 무엇일까??

코드의 구조를 보면 connection request를 하나 받을 때까지 기다린다. 계속 기다리고 있다가 connection 들어오면 write를 해주고 다시 while문을 와서 다음 request를 기다린다.

만약에 client1번이 request를 보냈는데, 이 client가 굉장히 느린 client였다고 가정해보자. 그 다음 엄청나게 빠른 client2가 request를 보냈다고 가정해보자. 근데 아직도 client1이 아직도 request를 못받아서 client2는 계속 기다리고 있어야 한다. 

--> IO blocking 대문에 기다려야하는 시간이 길어진다. 

 

해결방법)

  • 각각의 connection마다 새로운 process를 만든다 (옛날의 UNIX에서는 이렇게 동작함)
  • 이렇게 하면 memory를 너무 많이 쓰기 때문에 각각의 connection마다 새로운 thread를 생성한다.

 

문제점  -> 앞의 방법의 문제점은??

  • 만약에 request가 굉장히 많이 들어오면 thread가 엄청나게 생긴다
  • thread로 인한 overhead로 인해서 performance가 slow down된다
  • DoS 공격에도 취약해진다. 

해결 방법)

  • Thread Pool을 사용한다
  • Thread Pool은 request들어올때마다 Thread를 생성하는 것이 아닌, Pool을 만들어서 이 thread를 이용해서 request를 해결한다.
  • Thread를 반납하고 다시 사용될 수 있도록 한다. 

이상적인 thread pool size는 프로그램이 I/O bound인지 CPU bound인지에 따라 다르다. 

Thread pool size가 너무 크면 memory가 높게 사용되기 때문에 본인의 상황에 맞게 사용하여야 한다.

그래서 보통은 다음과 같은 식에 따라 thread의 개수를 정한다.

 

isClosed and isBound

  • isClosed()
    • 만약 ServerSocket이 닫혔으면 true를 리턴한다
    • ServerSocket object가 ServerSocket()으로 생성되고, port와 아직 연결되어 있지 않으면 닫힌 것으로 생각하지 않는다 -> false를 리턴
  • isBound()
    • ServerSocket이 한번이라도 port와 binding되었으면 True를 리턴한다.

문제는 isClosed()가 true라고 해서 열려있는 것은 아니다. 그럼 ServerSocket이 open되어있다는 사실을 어떻게 알 수 있을까?

--> isBound() && !isClosed()

 

 

728x90
반응형

'백엔드 > Network Programming' 카테고리의 다른 글

Non-blocking I/O in Java  (0) 2022.12.12
Socket Programming(2) - Socket for Client  (0) 2022.11.13
Socket Programming(1) - socket이란?  (0) 2022.11.13
URL and URI's key  (2) 2022.10.15
Internet protocols and layers  (2) 2022.09.09
728x90
반응형

JVM은 다른 프로그램을 실행시키는 것이 목적이다. 두 가지 기능이 있다고 말할 수 있는데,

  1. 자바 프로그램이 어느 기기나 운영체제 상에서도 실행될 수 있도록 한다
    • 자바와 os 사이에서 중개자 역할을 수행하여 OS에 상관없이 재사용을 가능하게 해준다.
  2. 프로그램 메모리를 관리하고 최적화 한다

JVM은 코드를 실행하고, 해당 코드에 대해 런타임 환경을 제공하는 프로그램에 대한 사양이다.

JVM은 보통 어떤 기기상에서 실행되고 있는 프로세스, 특히 자바 앱에 대한 리소스를 대표하고 통제하는 서버를 지칭한다.

자바 애플리케이션을 클래스 로더를 통해 읽어들이고, 자바 API와 함께 실행하는 역할을 한다.

  1. 프로그램이 실행되면 JVM은 OS로부터 프로그램에 필요한 메모리를 할당받는다.
  2. javac(자바 컴파일러)가 자바 소스코드를 읽고, 자바 바이트코드(.class)로 변환한다.
  3. 변경된 class 파일들을 클래스 로더를 통해 JVM 메모리 영역으로 로딩한다.
  4. 로딩된 class 파일들은 Execution engine을 통해 해석된다.
  5. 해석된 바이트 코드는 메모리 영역에 배치되어 수행된다. 이 때 JVM은 쓰레드 동기화나 가비지 컬렉션 같은 메모리 관리 작업을 수행한다.

[클래스 로더] : JVM은 런타임 시에 처음으로 클래스를 참조할 때 해당 클래스를 로드하고 메모리 영역에 배치시키는데 이 동적 로드를 담당하는 부분이 바로 클래스 로더이다.

Runtime Data Access

: JVM이 운영체제 위에서 실행되면서 할당받는 메모리 영역이다.

PC 레지스터, JVM 스택, 네이티브 메서드 스택, 힙, 메서드 영역

  • PC 레지스터 : 스레드가 어떤 명령어로 실행되어야 할지 기록하는 부분 (JVM 명령의 주소를 가진다)
  • 스택 : 지역변수, 매개변수, 메서드 정보, 임시 데이터 등을 저장
  • 네이티브 메서드 스택 : 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역
  • 힙 : 런타임에 동적으로 할당되는 데이터가 저장되는 영역. 객체나 배열 생성이 여기에 해당함. ( 힙에 할당된 데이터들이 가비지 컬렉터의 대상이 된다. JVM 성능에 영향을 미친다 )
  • 메서드 영역 : JVM이 시작될 때 생성되고, JVM이 읽은 각각의 클래스와 인터페이스에 대한 런타임 상수 풀, 필드 및 메서드 코드, 정적 변수, 메서드의 바이트 코드 등을 보관한다.

Garbage Collection

C나 C++은 개발자가 직접 메모리를 관리했지만 자바에서는 JVM이 프로그램 메모리를 관리한다. JVM은 Garbage Collection이라는 프로세스를 통해 메모리를 관리하는데 참조되지 않은 객체들을 탐색하여 삭제하고 삭제된 객체의 메모리를 반환하고 힙 메모리를 재사용하는 과정을 거친다.

 

 

https://gyoogle.dev/blog/computer-language/Java/Java 를 참조했습니다

728x90
반응형
728x90
반응형

Java에서의 Socket

Java에서는 socket class가 있어서 지원해준다.

  • java.net.Socket

    • client side의 TCP operation을 진행하는 기본적인 class
    • 밑에 함수들은 remote socket으로 connection을 open하는 함수이다
    • 기본 Constructor (생성자들) -> 여기서 host와 port는 remote(서버)의 주소와 portnumber이다. 
    public Socket(String host, int port) throws UnknownHostException,IOException
    public Socket(InetAddress host, int port) throws IOException
    
    try{
    	Socket toOReilly = new Socket("www.oreilly.com",80);
    } catch(UnknownHostException ex){
    	System.err.println(ex);
    } catch(IOException ex){
    	System.err.println(ex);
    }
  • remote와 local을 나누어서 local interface 어떤 것을 connect할지 정할 수도 있다.
public Socket(String host, int port, InetAddress interface, int localPort) throws UnknownHostException,IOException

그럼 위의 경우에는 remote만 적어주는데 local은 어떻게 되는 것일까?

→ OS에서 그냥 자동으로 선택해준다

 

또한, Socket을 만들고 바로 connect하는 것이 아니라, 만들고 나중에 connect할 수 도 있다.

public Socket()
public void connect(SocketAddress endpoint, int timeout) throws IOException

 

  • SocketAddress Class
    • connection endpoint ( remote host )를 나타내는 것을 도와주는 클래스
    • abstract class이고 생성자밖에 없다
    • socket connection정보(IP 주소, port number)를 제공하는 저장소 느낌이다
    • connect 함수를 사용할 수도 있다. 
    • Getter method
public SocketAddress getRemoteSocketAddress()
public SocketAddress getLocalSocketAddress()

  • InetSocketAddress Class
    • SocketAddress의 Subclass

 

Socket을 통해서 정보를 읽어보자

  • InputStream in = socket.getInputStream();

Socket을 통해서 서버에 써보자

  • OutputStream out = socket.getOutputStream();

 

예시 -> 사전

  • dict라는 TCP protocol에 port 2628로 "DEFINE eng-lat gold" 라고 request를 보내면 server는 gold의 의미를 English-to-latin 사전으로 definition을 보내준다.
package Socket;

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

public class DictClient3 {

    public static void main(String[] args){

        String host = "dict.org";
        try{
            Socket soc = new Socket(host,2628);
            OutputStream out = soc.getOutputStream();
            Writer writer = new OutputStreamWriter(out,"UTF-8");
            writer = new BufferedWriter(writer);
            InputStream in = soc.getInputStream();
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(in,"UTF-8"));
            String request = "DEFINE fd-eng-lat gold";
            writer.write(request);
            writer.flush();
            soc.shutdownOutput();

            for(String line = reader.readLine();line!=null;line=reader.readLine()){
                System.out.println(line);
            }
            soc.close();
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

 

 

Socket에 대한 정보 알아오기

Closed or Connected

  • isClosed() 함수는 socket이 닫혀있으면 true를 리턴하고, open되어 있으면 false를 리턴한다.
  • isConnected() 함수는 한번이라도 remote host와 연결되었다면 true를 리턴한다.
  • 만약 socket이 한번도 연결된 적이 없다면 isClosed() 함수는 open되어있지 않더라도 false를 return하게 된다. 
  • 따라서 socket connection이 제대로 open되어있는지 확인하려면 아래와 같이 확인해야 한다.
    • socket.isConnected() && !socket.isClosed()
728x90
반응형

'백엔드 > Network Programming' 카테고리의 다른 글

Non-blocking I/O in Java  (0) 2022.12.12
Socket Programming(3) - Socket for Server  (0) 2022.11.21
Socket Programming(1) - socket이란?  (0) 2022.11.13
URL and URI's key  (2) 2022.10.15
Internet protocols and layers  (2) 2022.09.09

+ Recent posts