이안의 평일코딩

JAVA의 정석 34일차 - 네트워크 본문

Back-end/Java

JAVA의 정석 34일차 - 네트워크

이안92 2020. 7. 30. 12:49
반응형

2020.07.30(목)

 

1. 서버 => IP 고정 (전화번호)
   클라이언트에서 연결 ==> 연결번호 (PORT) => (전화선)
   PORT => 0~65535 => 사용중인 PORT (0~1023)
   예 ) HTTP => 80
   SMTP => 25, FTP => 21 , TELNET => 23...
   기타) Spring : 8080
   React : 3000
   오라클 : 1521 MS-SQL : 1433
   머드 : 4000
   => 음성채팅 : 20000번
   => 화상채팅 : 30000번


   서버 제작
    1) bind => 핸드폰 개통
       ==== IP + PORT
    2) 대기상태 => listen
    3) 접속대기 => 접속 ==> accept() : 발신자 전화번호가 생성

                                                             ====== IP

    4) 저장 => 동기화

                   ====

                   ArrayList : 비동기화

                   Vector : 동기화

    5) 데이터 전송 : write()

    6) 사용자부터 요청 : readLine()

 

    서버에서 하는 역할

    ============

      (1) 사용자 요청받기

      (2) 요청처리 => 찾기

      (3) 결과값을 사용자 => 전송

 

   ==> 서버

      1) 1:1 (Peer To Peer)

      2) 1:다 => 데이터는 동일

                     사용자가 따라 요청을 할 수 있게 만든다

                     => 사용자 요청을 받아서 처리하는 프로그램이 존재

                     => 통신 => 별도 수행 (쓰레드)

 

2. annotation

package com.sist.ann;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(METHOD)
public @interface RequestMapping {
	public String value();
	
}
package com.sist.ann;

public class MovieModel {
	@RequestMapping("list")
	public void list() {
		System.out.println("목록 출력!!");
	}
	@RequestMapping("insert")
	public void insert() {
		System.out.println("데이터 추가");
	}
	@RequestMapping("update")
	public void update() {
		System.out.println("데이터 수정");
	}
	@RequestMapping("delete")
	public void delete() {
		System.out.println("데이터 삭제");
	}
	@RequestMapping("find")
	public void find() {
		System.out.println("데이터 찾기");
	}
	
}
package com.sist.ann;
import java.util.*;

import com.sun.org.apache.bcel.internal.classfile.Method;
public class UserMain {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.print("사용자 요청:");
		String ss = scan.next();
		MovieModel mm = new MovieModel();
		if(ss.equals("list")) {
			mm.list();
		}
		else if(ss.equals("delete")) {
			mm.delete();
		}
		else if(ss.equals("find")) {
			mm.find();
		}
		else if(ss.equals("update")) {
			mm.update();
		}
		else if(ss.equals("insert")) {
			mm.insert();
		}
	}

}
package com.sist.ann;
import java.lang.reflect.Method;
import java.util.*;
public class UserMain2 {
	
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.print("요청:");
		String ss = scan.next();
		try {
			Class clsName = Class.forName("com.sist.ann.MovieModel");
			// 클래스 정보 읽기
			Object obj = clsName.newInstance(); // 메모리 할당
			// 메소드 찾기
			Method[] methods = clsName.getDeclaredMethods();
			for(Method m : methods) {
				//System.out.println(m.getName());
				RequestMapping rm = m.getAnnotation(RequestMapping.class);
				if(rm.value().equals(ss)) {
					m.invoke(obj, null);
				}
			}
		}catch(Exception ex) {}
	}
}

 

3. 쓰레드

 => 자원을 보다 효율적으로 사용

 => 사용자에 대한 응답성이 향상

 => 작업이 분리된다 (소스가 간결화)

 => CPU를 효율적으로 사용 => 속도가 빨라진다

 => 실행중인 프로그램 => 프로세스 (쓰레드가 1개이상 존재)

 

쓰레드를 구현 방법

============

 1) 인터페이스

    Runnable =====> run()

    class A implements Runnable => 윈도우

 2) Thread 클래스 상속

    class A extends Thread => 일반 쓰레드

  쓰레드 실행 과정

    생성               대기(쓰레드에서 사용하는 데이터 수집)    쓰레드 등장

    new Thread()           start()                                          run()

===> 쓰레드의 동작 정의 run()구현

===> 쓰레드는 반드시 한개의 동작만 수행

         run() => 종료 => interrupt()

                => 일시정지 => sleep(), wait(), join()

 

package com.sist.temp;

class MyThread extends Thread{
	//동작
	public void run() {
		try {
			for(int i=1;i<=10;i++) {
				System.out.println(getName()+":"+i);
				Thread.sleep(50); // 1000분의 1초
			}
		}catch(Exception ex) {}
	}
}
public class Server {

	public static void main(String[] args) {
		MyThread t1 = new MyThread();
		MyThread t2 = new MyThread();
		MyThread t3 = new MyThread();
		
		// 생성 => JVM (1. 순위 결정 => 1~10) => 사용자 정의 쓰레드 (5)
		// 1: MIN_PRIORITY , 10 : MAX_PRIORITY , 5 : NORM_PRIORITY
		// 각 쓰레드마다 이름 부여 Thread-0 , Thread-1 .....
		// 자바프로그램은 MAX_PRIORITY(main), MIN_PRIORITY(gc)
		
		// 이름 부여
		t1.setName("서울");
		t2.setName("부산");
		t3.setName("강원");
		// 순위 부여
		t1.setPriority(10);
		t2.setPriority(1);
		t3.setPriority(1);
		// run을 호출 => start() => 자동으로 run()호출한다
		t1.start();
		t2.start();
		t3.start();	
	}
}

 

JProgressbar

package com.sist.temp;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ThreadRunnable extends JFrame implements Runnable, ActionListener{ // 인터페이스는 다중상속가능
	JProgressBar bar1 = new JProgressBar();
	JProgressBar bar2 = new JProgressBar();
	JProgressBar bar3 = new JProgressBar();
	JButton b1, b2;
	public ThreadRunnable() {
		bar1.setMinimum(0);
		bar1.setMaximum(100);
		bar1.setBackground(Color.white);
		bar1.setForeground(Color.cyan);
		bar1.setStringPainted(true); // 100%
		
		bar2.setMinimum(0);
		bar2.setMaximum(100);
		bar2.setBackground(Color.white);
		bar2.setForeground(Color.pink);
		bar2.setStringPainted(true); // 100%
		
		bar3.setMinimum(0);
		bar3.setMaximum(100);
		bar3.setBackground(Color.white);
		bar3.setForeground(Color.green);
		bar3.setStringPainted(true); // 100%
		
		b1 = new JButton("Start");
		b2 = new JButton("Exit");
		
		// 배치
		setLayout(null);
		bar1.setBounds(10, 15, 500, 30);
		bar2.setBounds(10, 50, 500, 30);
		bar3.setBounds(10, 85, 500, 30);
		
		JPanel p = new JPanel();
		p.add(b1);p.add(b2);
		p.setBounds(10, 120, 500, 35);
		
		add(bar1);
		add(bar2);
		add(bar3);
		add(p);
		
		setSize(540, 200);
		setVisible(true);
		
		b1.addActionListener(this);
	}
	public void go() { //프로그레스바 실행
		try {
			int a = (int)(Math.random()*101);
			for(int i=0; i<=a; i++) {
				bar1.setValue(i);
				Thread.sleep(100); //0.1초
			}
			int b = (int)(Math.random()*101);
			for(int i=0; i<=b; i++) {
				bar2.setValue(i);
				Thread.sleep(100); //0.1초
			}
			int c = (int)(Math.random()*101);
			for(int i=0; i<=c; i++) {
				bar3.setValue(i);
				Thread.sleep(100); //0.1초
			}
		}catch(Exception ex) {}
	}
	public static void main(String[] args) {
		new ThreadRunnable();

	}

	@Override
	public void run() { // 쓰레드 어떻게 동작할 것인지
		go();
		
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==b1) {
			new Thread(this).start();
		}
	}
}

 

MainFrame

package com.sist.temp;
import java.awt.*;
import javax.swing.*;
public class MainFrame extends JFrame{
	GameView gv = new GameView();
	public MainFrame() {
		add("Center",gv);
		setSize(1000, 750);
		setVisible(true);
	}
	public static void main(String[] args) {
		new MainFrame();
	}
}

GameView

package com.sist.temp;
import java.awt.*;
import javax.swing.*;
public class GameView extends JPanel{
	Image img;
	int x=100,y=300;
	public GameView() {
		img=Toolkit.getDefaultToolkit().getImage("C:\\javaDev\\dog.gif");
		new DogThread().start();
	}
	public void paint(Graphics g) {
		g.setColor(Color.white);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.drawImage(img, x, y, 300, 200, this);
	}
	
	class DogThread extends Thread{ //공유해야되는 것이 있을 때 멤버클래스 사용
		// 쓰레드 동작 메소드
		public void run() {
			while(true) {
				try {
				x+=5;
				if(x>850)
					x=10; 
				Thread.sleep(15);
				}catch(Exception ex) {}
			}
		}
	}
}

GameView (Multi Thread)

package com.sist.temp;
import java.awt.*;
import javax.swing.*;
public class GameView extends JPanel{
	Image img;
	//int x=100,y=300;
	DogThread[] dt = new DogThread[5];
	public GameView() {
		img=Toolkit.getDefaultToolkit().getImage("C:\\javaDev\\dog.gif");
		dt[0] = new DogThread(10, 50);
		dt[1] = new DogThread(10, 150);
		dt[2] = new DogThread(10, 250);
		dt[3] = new DogThread(10, 350);
		dt[4] = new DogThread(10, 450);
		//new DogThread().start();
		
		for(int i=0; i<5; i++) {
			dt[i].start();
		}
	}
	public void paint(Graphics g) {
		g.setColor(Color.white);
		g.fillRect(0, 0, getWidth(), getHeight());
		for(int i=0; i<5; i++) {
		g.drawImage(img, dt[i].x, dt[i].y, 300, 200, this);
		}
	}
	
	class DogThread extends Thread{ //공유해야되는 것이 있을 때 멤버클래스 사용
		int x,y;
		// 쓰레드 동작 메소드
		public DogThread(int x, int y) {
			this.x=x;
			this.y=y;
		}
		public void run() {
			while(true) {
				try {
				x+=5;
				if(x>850) {
					interrupt(); // 쓰레드 종료
				}
				int a = (int)(Math.random()*101);
					//x=10; 
				Thread.sleep(a);
				}catch(Exception ex) {}
			}
		}
	}
}

 

데이터 요청과 수신은 Thread로

4. 

서버 가동

 ServerSocket (Socket=전화기)

접속시에 처리

 accetp()

통신

 write()

 read()

 

Server

package com.sist.net;
import java.io.*;
import java.net.*;
import java.util.*;

public class Server implements Runnable {
	// 접속 받는 Socket => 교환 소켓
	ServerSocket ss = null;
	// 서버 가동
	// 한개의 컴퓨터에서는 여러개를 동시 수행이 불가능
	// 접속자 정보 저장
	Vector<Client> waitVc= new Vector<Client>();
	
	public Server() {
		try {
			ss = new ServerSocket(6543); // bind(ip, port) => listen()
			// 서버가동
			System.out.println("Server Start!!");
		}catch(Exception ex) {}
	}
	// 접속시에 처리
	public void run() {
		try {
			while(true) {
				Socket s = ss.accept(); // 접속을 했을 경우 => 접속자의 IP, PORT를 확인
				Client c = new Client(s); //접속자와 쓰레드 연결 시킴 (new라서 한사람당 하나씩 쓰레드 배정)
				waitVc.add(c); // 클라이언트 저장
				c.start(); // 접속자와 통신을 시작하라
			}
		}catch(Exception ex) {}
	}
	// 접속자마다 따로 통신이 가능
	class Client extends Thread {
		Socket s; // 접속한 클라이언트 연결
		OutputStream out; // 클라이언트에 결과값 전송
		BufferedReader in; // 클라이언트 요청시에 값을 받는 클래스
		public Client(Socket s) {
			try {
				this.s = s; // s는 client
				out = s.getOutputStream();
				in = new BufferedReader(new InputStreamReader(s.getInputStream()));
			}catch(Exception ex) {}	
		}
		// 통신시작
		public void run() {
			try {
				while(true) {
					String msg=in.readLine();
					// 채팅 문자열 받기
					for(Client user:waitVc) {
						user.out.write((msg+"\n").getBytes());
						// 네트워크 => 1byte => 받을때 (한글) => 2byte로 변환
					}
				}
			}catch(Exception ex) {}
		}
	}
	public static void main(String[] args) {
		Server server = new Server(); // 서버가동
		new Thread(server).start(); // 접속처리 => 접속을 기다린다
	}
}

 

Client

package com.sist.net;
import java.net.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Client extends JFrame implements Runnable, ActionListener{
	JTextArea ta;
	JTextField tf;
	JButton b1, b2;
	// 네트워크 관련 라이브러리
	Socket s; // 연결기계 (전화기)
	BufferedReader in;
	OutputStream out;
	
	public Client() {
		ta = new JTextArea();
		ta.setEditable(false); //편집불가 입력만가능하게
		JScrollPane js = new JScrollPane(ta);
		tf = new JTextField(30);
		tf.setEnabled(false);
		b1 = new JButton("접속");
		b2 = new JButton("종료");
		
		JPanel p = new JPanel();
		p.add(tf);p.add(b1);p.add(b2);
		
		add("Center",js);
		add("South", p);
		setSize(500, 500);
		setVisible(true);
		
		b1.addActionListener(this); // 접속
		b2.addActionListener(this); // 종료
		tf.addActionListener(this); // 엔터 => 입력된 값을 서버로 전송
		
	}
	
	// 서버에 들어오는 결과값을 받아서 출력
	
	public void run() {
		try {
			while(true) {
				String msg = in.readLine();
				ta.append(msg+"\n");
			}
		}catch(Exception ex) {}
	}
	
	public static void main(String[] args) {
//	try {
//		Socket s = new Socket("211.999.999.999",6543); // s는 Server
//	}catch(Exception ex) {}
		new Client();
}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==b1) {
			try {
				s=new Socket("211.999.999.999", 6543);
				in = new BufferedReader(new InputStreamReader(s.getInputStream()));
				// 서버에서 값을 읽어 온다
				out = s.getOutputStream();
				// 서버로 값을 보낼 때 사용
				tf.setEnabled(true); // 활성화
				b1.setEnabled(false);
				
			}catch(Exception ex) {}
			new Thread(this).start();
			// 서버로부터 값을 읽어 와라
		}
		else if(e.getSource()==tf) {
			try {
				String msg=tf.getText();
				if(msg.length()<1) return;
				out.write((msg+"\n").getBytes());
				tf.setText("");
			}catch(Exception ex) {}
			
		}
		
	}
}
반응형
Comments