JAVA

Java Network and Thread

jmeen 2021. 8. 11. 16:10
728x90

JAVA Thread

Process: 실행중인 하나의 프로그램
Thread: 프로세스 내의 하나의 작업 흐름

 

 

 

Thread의 상태와 Multi Thread 프로그램의 작성 방법

Thread의 상태

상태 열거 상수 설명
객체 생성 NEW 쓰레드 객체가 생성. 아직 start() 메서드가 호출되지 않은 상태
실행 대기 RUNNABLE 실행 상태로 언제든지 갈 수 있는 상태
일시 정지 WAITING 다른 쓰레드가 통지할 때까지 기다리는 상태
TIMED_WAITING 주어진 시간 동안 기다리는 상태
BLOCKED 사용하고자 하는 객체의 락이 풀릴 때까지 기다리는 상태
종료 TERMINATED 실행을 마친 상태

Multi Thread 프로그램 작성 방법

  -  java.lang.Thread 클래스를 이용하는 방법
  -  java.lang.Runnable 인터페이스를 이용하는 방법


java.lang.Thread 클래스를 이용하는 방법

main 메소드를 포함하는 클래스

public class Multithread {
  public static void main(String args[]) {
    Thread thread = new DigitThread();    	 // 스레드를 생성
    thread.start();    		   		 // 스레드를 시작
    for (char ch = 'A'; ch <= 'Z'; ch++) {
      System.out.print(ch);
    }
  }
}

숫자를 출력하는 스레드 클래스

public class DigitThread extends Thread {
  public void run() {
    for (int cnt = 0; cnt < 10; cnt++) {
    	System.out.print(cnt);
    }
  }
}

java.lang.Runnable 인터페이스 연습

 

 

 


Java Network and Thread - TCP Socket Programming

TCP Socket Programming : TCP 소켓의 특징

- 스트림(stream) 통신 프로토콜
- 양쪽의 소켓이 연결된 상태에서 통신이 가능하다(연결지향 프로토콜)
- 신뢰성 있는 데이터 통신
- 한번 연결되면 끊어질 때까지 송신한 데이터는 차례대로 목적지의 소켓에 전달
- 자바는 java.net 패키지에 관련 클래스를 제공
  - TCP 소켓 프로그래밍을 쉽게 할 수 있도록 돕는다
- 라이브러리의 사용법과 작동 순서를 명확하게 이해하고 있어야 한다
- ServerSocket과 Socket 클래스를 사용한다

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressEx {

	public static void main(String[] args) {
		// 내 ip 확인
		try {
			InetAddress local = InetAddress.getLocalHost();
			System.out.println("Local IP" + local.getHostAddress());
		} catch (Exception e) {
			e.printStackTrace();
		}

		printServerIp("www.google.com");
	}

	private static void printServerIp(String hostName) {
		try {
			InetAddress[] remotes = InetAddress.getAllByName(hostName);
			for (InetAddress remote : remotes) {
				System.out.println(hostName + " : " + remote.getHostAddress());
			}

		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

	}
}

TCP 소켓 프로그래밍 절차

ServerSocket과 Socket

ServerSocket : 클라이언트의 연결 요청을 기다리면서 연결 요청에 대한 수락을 담당
Socket : 클라이언트와 통신을 직접 담당한다

 

서버- 클라이언트 연동 시스템 

1. 서버 구동부

package com.javaex.network.echoserver;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

	public static void main(String[] args) {
		// 서버 소켓
		ServerSocket serversocket = null;
		try {
			// 바인드 : 주소와 포트 연결
			serversocket = new ServerSocket();
			InetSocketAddress ip = new InetSocketAddress("192.168.0.11", 10000);

			serversocket.bind(ip);

			System.out.println("<서버 시작>");
			System.out.println("[연결을 기다립니다.]");

			while (true) {
				Socket socket = serversocket.accept(); // 연결 대기
				Thread thread = new Thread(new ServerThread(socket));

				// 쓰레드 시작
				thread.start();


			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				serversocket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

1-1. 서버 Thread

package com.javaex.network.echoserver;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.*;

public class ServerThread extends Thread {
	// 소켓
	private Socket socket;

	// 생성자
	public ServerThread(Socket socket) {
		this.socket = socket;

	}
	@Override
	public void run() {
		try {
			// 쓰레드의 시작
			// 접속 성공시 : 클라이언트 정보 확인
			InetSocketAddress remote = (InetSocketAddress) socket.getRemoteSocketAddress();
			System.out.println("[클라이언트가 접속되었습니다.]");
			System.out.println(remote.getAddress() + ":" + remote.getPort());

			// 클라이어트로부터 메세지 수진
			// 스트림 열기
			InputStream is = socket.getInputStream();
			// 주고 받을 데이터 text -> reader
			Reader isr = new InputStreamReader(is, "UTF-8");
			BufferedReader br = new BufferedReader(isr);

			// 클라이언트 echo back 을 하기 위한 스트림 열기
			OutputStream os = socket.getOutputStream();
			Writer osw = new OutputStreamWriter(os, "UTF-8");
			BufferedWriter bw = new BufferedWriter(osw);

			// 데이터 읽기
			String message;
			while (true) {
				message = br.readLine();
				if (message == null) {
					System.out.println("[접속 종료]");
					break;
				}
				System.out.println("클라이언트로부터 메세지 : " + message);
				System.out.println("Echo back : " + message);

				// 클라이언트로 echo back
				bw.write("[ECHO]: " + message);
				bw.newLine();
				bw.flush();
			}

			// 후처리
			bw.close();
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

2. 클라이언트

package com.javaex.network.echoserver;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Scanner;

public class Client {

	public static void main(String[] args) {
		Socket socket = null;

		try {
			// 소켓 생성 : 데이터 통신용
			socket = new Socket();

			// 시작 메세지
			System.out.println("<클라이언트 시작>");
			System.out.println("[연결 요청]");

			// 접속 시도
			InetSocketAddress server = new InetSocketAddress("192.168.0.16", 10000);
			socket.connect(server);
			System.out.println("[서버에 연결되었습니다.]");

			// 스트림 열기
			OutputStream os = socket.getOutputStream();
			Writer osw = new OutputStreamWriter(os, "UTF-8");
			BufferedWriter bw = new BufferedWriter(osw);

			InputStream is = socket.getInputStream();
			Reader isr = new InputStreamReader(is);
			BufferedReader br = new BufferedReader(isr);

			// 키보드에서 메세지 입력
			Scanner sc = new Scanner(System.in);
			// scanner에서 /q입력하면 종료

			while (true) {
				String message = sc.nextLine(); // 한 줄 입력
				if (message.equals("/q")) {
					System.out.println("종료");
					break;
				}
				// 서버로 메세지 전송
				bw.write(message);
				bw.newLine();
				bw.flush();
				System.out.println("서버로 전송한 메세지 :" + message);

				String echoMsg = br.readLine(); // 한줄 읽기
				System.out.println("서버로부터 ECHO된 메시지" + echoMsg);
			}
			sc.close();
			bw.close();
			br.close();

			// 종료
			System.out.println("<클라이언트 종료>");

		} catch (ConnectException e) {
			System.err.println("[접속이 거부되었습니다.]");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				socket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}