1. java.lang패키지 

- 가장 기본이 되는 패키지이며, import문 없이도 사용이 가능하다.

- 최상위 객체인 Object클래스 외에도, String, Math, Wrapper클래스가 있다.

 

1-1. Object클래스의 주요 메서드

+equals() 객체의 주소값을 비교한다.
+hashCode() 객체의 해쉬코드를 반환한다.
*모든 객체는 자신을 구분하는 고유의 해시코드를 가진다.
*자바에서는 해싱 기법을 통해 다양한 객체를 구분하여 저장한다.
+getClass() 객체의 인스턴스를 반환한다.
+toString() "클래스이름+@+해쉬코드"문자열을 반환한다.
#clone() 객체를 얕게 복사하여 반환한다.
(객체 내 포함된 객체까지는 복사되지 않으므로, 겉의 객체만 복사되면, 안의 객체는 사실상 동일한 곳을 참조하므로 복사된 객체를 수정할 때 기존 객체의 안쪽 객체 정보까지 수정될 수 있다.)

 

1-2. String클래스

- 이부분은 별도로 정리하였다.

- 간략하게 String은 "변경 불가하다"라는 점과, 그렇기에 StringBuffer와 StringBuilder로 처리할 수 있다는 점만 기억하자..

https://why-dev.tistory.com/31?category=928637 

 

[자바의 정석_복습] String 객체에 대한 이해

심플한 개발 [자바의 정석_복습] String 객체에 대한 이해 본문 JAVA/문자열, 배열 [자바의 정석_복습] String 객체에 대한 이해 심플한 개발 2022. 3. 15. 19:08 Prev 1 ··· 5 6 7 8 9 10 Next

why-dev.tistory.com

 

1-3. Math클래스

+round() : long 소수점 첫째자리에서 반올림을 한다.
(사용시, 10^x 만큼 곱하고 나누어 원하는 만큼 반올림하면 된다.)
+ceil() 올림
+floor() 버림
.... 기타

 

1-4. Wrapper클래스

- Boolean, Character, Number가 있으면 Number안에 정수형, 실수형 변수객체들이 있다.

- 문자열을 숫자로 변환하는 법 : Integer.parseInt("문자열")

- 오토박싱과 언박싱

https://why-dev.tistory.com/45

 

[자바_문법] Wrapper 클래스 이해

Wrapper클래스  Wrapper : Boolean, Byte, Integer, Long, Float, Double Wrapper클래스의 오토-언박싱과 오토-박싱  - Auto-Boxing : [Auto-Boxing 예제_Object객체배열 안에 다양한 타입의 기본형 리터럴 입력..

why-dev.tistory.com

 

 

 

[참조]

자바의 정석, 남궁성  -- 요약한 내용입니다.

'Language > Java' 카테고리의 다른 글

[자바_문법] 쓰레드  (0) 2022.04.17
[자바의정석_예제] 객체지향프로그래밍2  (0) 2022.04.13
[자바_API] 입출력 I/O  (0) 2022.04.05
[자바_API] 네트워킹  (0) 2022.04.04
[자바의정석_복습] 예외처리  (0) 2022.03.28

1. 스트림이란? 데이터를 운반하는데 사용되는 연결통로

  [생각] BJ는 온라인방송을 할 때, 왜 "스트리밍 중"이라고 할까?

 

2. 바이트기반 스트림_InputStream/OutPutStream 추상클래스 상속

입력스트림 출력스트림 입출력 대상의 종류
FileInputStream FileOutputStream 파일
ByteArrayInputStream ByteArrayOutputStream 메모리(byte배열)
PipedInputStream PipedOutputStream 프로세스(프로세스간의 통신)
AudioInputStream AudioOutputStream 오디오장치
.... .... ....

(1) InputStream 메서드

리턴타입 메소드  
int read() 입력 스트림에서 1byte씩 읽고 byte값을 int으로 반환
int read(byte[] b) 입력 스트림에서 1byte씩 읽어 byte배열에 저장, 읽은 갯수를 반환
int read(byte[] b, int off, int len) 입력 스트림에서 off부터 시작하여, len개를 읽어 byte 배열에 저장,
읽은 갯수를 반환
void close() 시스템의 자원을 반환하고 입력 스트림을 닫는다. (파일)

▶ read() 메소드

InputStream is = new FileInputStream("C:/test.jpg");
int readByte;
//모든 InputStream 하위 객체 read() : 읽은 내용이 없으면 -1 반환
while((readByte = is.read()) != -1){}

▶ 키보드에서 읽어오기 : System.in

package mymain.input;

import java.io.InputStream;

public class _01_KeyboardInputTest {

	public static void main(String[] args) throws Exception {
		int ch;
		
		//키보드의 입력값을 받는 inputStream
		//System객체 내에 포함관계로 inputStream이 생성되어 있는 상태
		InputStream is = System.in; 
		
		System.out.println("종료하려면 [Ctrl+Z]");
		
		while((ch = is.read()) != -1) {
			System.out.printf("%c",ch);
		}
	}

▶ 파일에서 읽어오기 : FileInputStream("파일경로")

package mymain.input;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class _02_FileInputTest {
	public static void main(String[] args) throws IOException {
		InputStream is = new FileInputStream("src/mymain/input/_02_FileInputTest.java");
		
		int ch;
		
		while((ch = is.read())!=-1) {
			System.out.printf("%c",ch);
		}
		
		is.close();
	}
}

▶ 네트워크에서 읽어오기 : URL(String url) > openStream()

package mymain.input;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

public class _03_NetWorkInputStream {
	public static void main(String[] args) throws IOException {
		URL url = new URL("https://www.naver.com");
		InputStream is = url.openStream();
		
		int ch;
		
		while((ch = is.read())!=-1) {
			System.out.printf("%c",ch);
		}
	}
}

 

(2) OutputStream 메서드

리턴타입 메소드  
void write() 출력 스트림으로 1byte씩 보낸다.
void write(byte[] b) 출력 스트림에 byte[] b의 값을 보낸다.
void write(byte[] b, int off, int len) 출력 스트림에 off부터 시작해서 len개 만큼 보낸다.
void flush() 버퍼에 잔류하는 모든 바이트를 출력
void close() 시스템의 자원을 반납하고 출력 스트림을 닫는다. (파일)

▶ read() 메소드

OutputStream os = new FileOutputStream("C:/test.txt");
byte[] data = "ABC".getBytes();
for(int i = 0; i < data.length; i++){
	os.write(data[i]);
}

 

▶ 모니터로 출력하기 : System.out

package mymain.output;

import java.io.IOException;
import java.io.OutputStream;

public class _01_MonitorTest {
	public static void main(String[] args) throws IOException {
		OutputStream os = System.out;
		
		//자바 -> 출력 스트림 -> 키보드버퍼로 문자를 전송
		os.write(65);
		
		String msg = "안녕";
		byte[] msg_bytes = msg.getBytes();
		os.write(msg_bytes);
		
		int n = 1004;
		String s = String.valueOf(n);
		os.write(s.getBytes());
		
		boolean bOk = true;
		String b = String.valueOf(bOk);
		os.write(b.getBytes());
		
		//키보드 커퍼를 비우면서 콘솔로 전송
		os.flush();
	}
}

▶ 파일로 출력하기 : FileOutputStream("파일경로");

package mymain.output;

import java.io.FileOutputStream;
import java.io.OutputStream;

public class _02_FileOutTest {

	public static void main(String[] args) throws Exception{
		OutputStream os = new FileOutputStream("a.txt");
		
		os.write('A');
		
		String name = "홍길동";
		byte[] sArr = name.getBytes();
		os.write(sArr);
		
		int n = 1994;
		os.write(String.valueOf(n).getBytes());
		
		os.flush();
		
		os.close();
	}

}

 

(3) 바이트 배열 단위로 읽어오기/보내기

가. InputStream/OutputStream의 read(byte[] b), write(byte[] b) 사용

package mymain.input;

import java.io.FileInputStream;
import java.io.InputStream;

public class _04_InputStream_Array {
	public static void main(String[] args) throws Exception{
		InputStream is = new FileInputStream("src/mymain/input/_04_InputStream_Array.java");
		
		int readByteNo;
		byte[] readBytes = new byte[8];
        //           is.read(readBytes, 1, 8); <- index 1부터 8개
		readByteNo = is.read(readBytes);
		
		for(int i = 0; i < readBytes.length; i++) 
			System.out.printf("%c",readBytes[i]);
		
		is.close();
	}
}
package mymain.output;

import java.io.FileOutputStream;
import java.io.OutputStream;

public class _03_OutputStream_Array {
	public static void main(String[] args) throws Exception{
		OutputStream os = new FileOutputStream("a2.txt");
		
		byte[] output = "ABC".getBytes();
		
		// os.write(output,1,2); /*: index1부터 2개*/
		os.write(output);
		
		os.close();
	}
}

 

나. ByteArrayInputStream/ByteArrayOutputStream 객체 사용

package mymain.input;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;

public class _04_InputStream_Array2 {
	public static void main(String[] args) throws Exception{
		byte[] inSrc = {0,1,3,4,5,6};
		byte[] outSrc = null;
		
		ByteArrayInputStream input = null;
		ByteArrayOutputStream output = null;
		
		input = new ByteArrayInputStream(inSrc);
		output = new ByteArrayOutputStream();
		
		int data = 0;

		while((data = input.read()) != -1) {
			output.write(data);
		}
		
		outSrc = output.toByteArray();
		
		System.out.println("Input Source : "+Arrays.toString(inSrc));
		System.out.println("Output Source : "+Arrays.toString(outSrc));
	}
}

>> 결과

Input Source : [0, 1, 3, 4, 5, 6]
Output Source : [0, 1, 3, 4, 5, 6]

 

 

3. 문자기반 스트림_Reader,Writer 추상클래스 상속

입력스트림 출력스트림 입출력 대상의 종류
FileReader FileWriter 파일
ByteArrayReader ByteArrayWriter 메모리(byte배열)
PipedReader PipedWriter 프로세스(프로세스간의 통신)
StringReader StringWriter 문자열
.... .... ....

 

4. 보조스트림_Filterxxxxx, Bufferedxxxxx, Objectxxxxx

입력스트림 입출력 대상의 종류
Filterxxxxx 필터를 이용한 입출력 처리
Bufferedxxxxxx 버퍼를 이용한 입출력 향상 (버퍼에 바이트/문자 올려두고, 한 줄씩 출력 가능-nextLine())
Objectxxxxxx 객체 직렬화/역직렬화

 

 

 

[참조]

이것이 자바다 

자바의 정석, 남궁성 지음

1. 네트워킹이란? 

두 대 이상의 컴퓨터를 케이블로 연결하여 네트워크를 구성하는 것

* 자바에서는 java.net 패키지를 활용해 네트워크 어플의 데이터 통신을 쉽게 작성 가능하다.

https://www.youtube.com/watch?v=yR4hnj5XNP4&t=5s 


  [참조 : OSI 7 계층, TCP 4 layer]
  https://velog.io/@dyllis/OSI-7%EA%B3%84%EC%B8%B5-%EC%A0%95%EB%A6%AC
  - OSI 7계층 : 물리계층 - > 데이타 링크 계층/ -> 네트워크계층/ -> 전송계층 / -> 세션 계층 -> 표현 계층 -> 응용계층

 

2. 클라이언트와 서버

* 서비스란? 서버가 클라이언트로부터 요청받은 작업을 처리하여 그 결과를 제공하는 것

- 클라이언트와 서버와의 관계

클라이언트 <-> 서버
[1] 연결을 요청
[3] 처리 요청
  [2] 연결 수락
[4] 처리/응답 (서비스 제공)

- 서버의 모델

명칭 서버 기반 모델 (server-based model) P2P모델(peer-to-peer model)
내용 전용 서버를 둠 전용 서버 없이 각 클라이언트가 서버역할 동시수행
장/단점 - 안정적인 서비스 제공 가능
- 공유데이터의 관리와 보완이 용이
- 서버 구축 비용과 관리 비용이 든다.
- 서버 구축 및 운용비용을 절감 가능
- 자원의 활용을 극대화 가능
- 자원의 관리가 어려움
- 보안이 취약

 

3. IP주소 : "내 컴퓨터"를 나타내는 주소. 

https://www.youtube.com/watch?v=IAS3U5ZiI8c 

코딩하는거니님의 IP에 대한 설명

- 4byte로 0~255사이로 표현 (ex. 255.255.255.0)

- 앞의 3byte는 네트워크 주소 + 뒤 1byte는 호스트 주소

- 명령프롬프트에서 "ipconfig/All" 또는 "ipconfig"를 치면 확인 가능

 

3-1. java.net패키지의 InetAddress클래스

[1] 로컬 컴퓨터에서 IP 주소 얻으려 할 때

//객체 생성
InetAddress ip = InetAddres.getLocalHost();

//객체 이름, 주소 추출 : String으로 반환
String ipName = ip.getHostName();
String ipAddress = ip.getHostAddress();

 

[2] 도메인 이름으로 IP 주소 얻으려 할때

//도메인에서 단일 ip 주소 가져오기
InetAddress ip = InetAddress.getByName("www.naver.com");

//도메인에서 여러개의 ip주소 가져오기
InetAddress[] ipArr = InetAddress.getAllByName("www.naver.com");

 

4. URL(Uniform Resource Locator)

- 형태 : 프로토콜://호트스명:포트번호/경로명/파일명?쿼리스트링#참조 

- 예시 ) http://www.naver.com:80/sample/hello.html?refer=codechobo#index1

프로토콜 서버와 통신할 때 사용되는 통신규약(HTTP)
호스트명 자원을 제공하는 서버명(ex.www.naver.com)
포트번호 통신에서 사용되는 서버의 포트 번호
경로명 경로
파일명 파일명 (ex. index.html)
쿼리 URL에서 ? 이후의 부분 
참조 URL에서 # 이후의 부분

※ Filezilla에서 보는 호스트와 포트, 사용자명 개념

→ 호스트 : 도메인을 작성하거나, ip주소를 작성하는 공간

→ 사용자명 : 해당 호스트 사용자명 (보통 회사에서 지정해주는 게 있다.)

→ 비밀번호 : 접속 시 비밀번호

→ 포트 : 통신에서 사용되는 서버의 포트 번호 (일반적으로 FTP포트는 21이 가장 많다)

 

5. 소켓 프로그래밍

[1] 소켓에 대하여

- 소켓이란?

  프로세스 간의 통신에 사용되는 양쪽 끝단으로

  네트워크 기능(OS의 네트워크 라이브러리)을 용이하게 이용하기 위한 각 언어별 모듈(객체)이다.

- 모든 소켓은 각각 자신만의 InputStream, OutputStream을 가지고 있다.

- JVM은 각 운영체제별로 다르게 작동하며, 각 운영체제의 네트워크 라이브러리에 맞춘 소켓을 사용한다.

[2] 포트란?

- 같은 컴퓨터 내에서 프로그램을 식별하는 번호

- 0~65535 범위 (총 65536개) 값을 가질 수 있다.

- 세 가지 범위로 구분

(1) Well Known : 0~1023, ICANN가 애플리케이션용으로 미리 예약한 포트로 FTP, Telnet 등에서 사용

(2) Registed : 1024~49151, 회사에서 등록해서 사용 가능한 포트값

(3) Dynamic or Private : 49152~65535, 운영체제가 부여하는 동적 포트 또는 개인 목적의 포트

 

6. TCP와 UDP 프로토콜

- 클라이언트와 서버를 연결하는 프로토콜에는 여러가지 종류가 있다. 

- TCP,UDP 외에도 통신 프로토콜로 HTTP 등이 있다.

항목 TCP UDP
연결방식 연결기반
- 연결 후 통신(전화기)
비연결기반
- 연결 없이 통신 (소포)
특징 데이터의 경계를 구분 안함 (바이트스트림)
신뢰성 높은 데이터 전송
- 데이터의 전송순서가 보장됨
- 데이터의 수신여부를 확인함
  (데이터가 손실되면 재전송됨)
- 패킷을 관리할 필요가 없음
UDP보다 전송속도가 느림
데이터 전송용량의 제한이 없음
데이터의 경계를 구분함(datagram)
신뢰성 낮은 데이터 전송
- 데이터의 전송순서가 바뀔 수 있음
- 데이터의 수신여부를 확인안함
  (데이터가 손실되어도 알 수 없음)
- 패킷을 관리해주어야 함
TCP보다 전송 속도가 빠름
1회 전송량 512byte
관련 클래스 Socket

ServerSocket
DatagramSocket
DatagramPacket
MulticastSocket
통신 방식 Uni-cast (1:1) BroadCast(불특정 다수) 
- local broadcast
pf. xxx.xxx.xxx.255 로 일괄 전달
- global broadcast
pf. 255.255.255.255 로 일괄 전달

MultiCast(특정 다수) 
pf. 회원 가입 대상자들만 전달
pf. 224.0.0.1 ~ 239.255.255.255

[참고] 

  유니캐스트 VS 브로드캐스트 VS 멀티캐스트
  https://m.blog.naver.com/wnrjsxo/221250742423

 

7. TCP 소켓 프로그래밍

- "이것이 자바다" 영상의 아래 그림이 TCP를 이해하는데 많은 도움을 주는 것 같다. 

[이것이 자바다] 참조

[1] 송신 방법

package tcpProtocol;

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

public class BasicSend {

	public static void main(String[] args) throws Exception{
		//[1] 소켓을 연다.(연결할 서버소켓의 주소와 포트를 작성)
		Socket socket = new Socket("localhost",50000);
		OutputStream os = socket.getOutputStream();
		
		for(int i = 1; i <= 3; i++) {
			//[2] 소켓의 OutputStream을 통해 byte단위의 데이터를 전송한다.
			String data = "데이터"+i;
			os.write(data.getBytes("UTF-8"));
		}
		os.flush();
		
		//[3] 소켓 연결 끊기
		//socket.close(); --> 의도적인 종료 : -1 값을 전달한다.
		socket.close();
	}

}

 

[2] 수신 방법

package tcpProtocol;

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

public class BasicAccept {

	public static void main(String[] args) throws Exception{
		//[1] 서버 소켓을 연다.
		ServerSocket serverSocket = new ServerSocket(50000);
		
		try {
			//[2] 소켓을 연다.
			Socket socket = serverSocket.accept();
			InputStream is = socket.getInputStream();
			
			//무한 루프로 수신 대기
			System.out.println("[수신 데이터]");
			while(true) {
				//[3] InputStream을 통해 바이트단위 데이터를 가져온다.
				byte[] byteArr = new byte[300]; //한글 3byte->100자씩 읽을 것
				int len = is.read(byteArr);
				if(len == -1) break;
				String data = new String(byteArr,0,len,"UTF-8");
				//[4] 수신 data 콘솔에 출력
				System.out.println(data);
			}
		} catch (IOException e) {
			System.out.println("[연결 종료]");
		}
	
	}

}

 

[연습 예제_1] TCP 1:1 전송방식으로 로컬컴퓨터에서 에코메시지 전달하기

<Client>

package tcpProtocol;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.*;

public class Client extends JFrame{
	
	JTextArea textMonitor;
	JTextField textInput;
	JButton button;
	Socket socket;
	
	Client(){
		/* Initial Window UI Design  */
		super("Chat for Client");
		setLocation(300,300);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		init_UiDesign();
		pack();
		
		/* TCP Socket Communication */
		init_buttonAction();
		init_socket();
		
	}//end Client()
	
	/////////////////////////////////////////////////////
	
	/* TCP Socket Communication Method */
	
	private void init_buttonAction() {
		
		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String textMessage = String.format("[사용자] %s%n", textInput.getText().trim());
				if(textMessage.isEmpty()) {
					JOptionPane.showMessageDialog(textMonitor,"메세지를 입력하세요.");
					return;
				}else {
					//textMonitor.append(textMessage);
					echo_message();
					textInput.setText("");
					return;
				}
			}
		});
	}
	
	private void init_socket() {
		try {
			socket = new Socket("localhost",50000);
		} catch (UnknownHostException e) {
			System.out.println("해당 호스트를 찾을 수 없습니다.");
		} catch (IOException e) {
			System.out.println("포트가 비정상적으로 닫혀있습니다.");
		}
	}

	protected void echo_message() {
		send_message();
		receive_message(); 
	}


	private void send_message() {
		//send Message to server
		try {
			OutputStream outStream = socket.getOutputStream();
			String userMessage = String.format("[사용자] %s%n", textInput.getText().trim());
				//append message to Monitor
			textMonitor.append(userMessage);
			outStream.write(userMessage.getBytes());
			outStream.flush();
		} catch (IOException e) {
			System.out.println("전송에 오류가 발생했습니다.");
		}
	}
	
	private void receive_message() {
		//receive Message from server
		try {
			byte[] readBytes = new byte[300];
			int readNum = socket.getInputStream().read(readBytes);
			String echoedMessage = new String(readBytes,0,readNum);
			
			//append message to Monitor
			textMonitor.append(echoedMessage);
		} catch (IOException e) {
			System.out.println("수신에 오류가 발생했습니다.");
		}
	}

	

	/* UI Design Method */
	
	private void init_UiDesign() {
		//textMonitor : where chat text reveals
		textMonitor = new JTextArea();
		textMonitor.setBackground(new Color(0x7BC4C4));
		textMonitor.setEditable(false);
		JScrollPane jsp = new JScrollPane(textMonitor);
		textMonitor.setPreferredSize(new Dimension(300,200));
		this.add(jsp);
		
		//textInput : where user types texts & send
		JPanel jpl = new JPanel(new BorderLayout());
		textInput = new JTextField();
		button = new JButton("전송");
		jpl.add(textInput);
		jpl.add(button,"East");
		this.add(jpl,"South");
	}

	public static void main(String[] args) {
		new Client();
	}//end main
}

 

<Server>

package tcpProtocol;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.*;

public class Server extends JFrame{
	
	JTextArea textMonitor;
	JTextField textInput;
	JButton button;
	ServerSocket serverSocket;
	Socket socket;
	
	Server(){
		/* Initial Window UI Design  */
		super("Chat for Server");
		setLocation(300,300);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		init_UiDesign();
		pack();
		
		/* TCP Socket Communication */
		init_socket();
		
	}//end Client()
	
	
	/////////////////////////////////////////////////////
	
	/* TCP Socket Communication Method */
	
	private void init_socket() {
		try {
			serverSocket = new ServerSocket(50000);
			socket = serverSocket.accept();
			while(true) {
				//receive Message from client
				byte[] readBytes = new byte[300];
				int readNum = socket.getInputStream().read(readBytes);
				String[] userMessage = new String(readBytes,0,readNum).split("]");
				
				//append message to Monitor
				textMonitor.append(new String(readBytes,0,readNum));
				
				//send Message to client
				OutputStream outStream = socket.getOutputStream();
				String echoedMessage = String.format("[에코]%s%n",userMessage[1]);
					//append message to Monitor
				textMonitor.append(echoedMessage);
				outStream.write(echoedMessage.getBytes());
				outStream.flush();
			}
			
		} catch (IOException e) {
			JOptionPane.showMessageDialog(this, e.getMessage());
		}
		
	}

	/* UI Design Method */
	
	private void init_UiDesign() {
		//textMonitor : where chat text reveals
		textMonitor = new JTextArea();
		textMonitor.setBackground(new Color(0x7BC4C4));
		textMonitor.setEditable(false);
		JScrollPane jsp = new JScrollPane(textMonitor);
		textMonitor.setPreferredSize(new Dimension(300,200));
		this.add(jsp);
		
		//textInput : where user types texts & send
		JPanel jpl = new JPanel(new BorderLayout());
		textInput = new JTextField();
		button = new JButton("전송");
		jpl.add(textInput);
		jpl.add(button,"East");
		this.add(jpl,"South");
	}

	public static void main(String[] args) {
		new Server();
	}//end main
}

>>결과

 

 

8. UDP 소켓 프로그래밍

- UDP는 소포와 같이 서버소켓을 통한 연결 없이 수신, 송신만 가능한 형태이다.

- 통신 선로가 고정적이지 않음

- 데이터 손실이 발생 가능

- 대신 TCP보다는 빠르게 전송이 가능하다

이것이 자바다 참조

[1] 송신하는 법

//송신하는 법
//[1] DatagramSocket를 연다.
DatagramSocket datagramSocket = new DatagramSocket();
//만약, multi-cast방식으로 전달할 경우, 
//MulticastSocket multicastSocket = new MulticastSocket();
InetAddress ia = InetAddress.getByName("localhost"); //수신되는 곳의 주소

//[2] 전달할 데이터를 패킷으로 패킹한다.
String data = "전달 데이터";
byte[] byteArr = data.getBytes("UTF-8"); //UTF-8방식으로 바이트 변환
DatagramPacket packet = new DatagramPacket(
	byteArr, byteArr.length,ia,포트번호
);

//[3] DatagramSocket을 통해 패킷을 전송한다.(바이트단위로 전송된다)
datagramSocket.send(packet);

//[4] DatagramSocket을 닫아준다.
datagramSocket.close();

[2] 수신하는 법

//수신하는 법
//[1] DatagramSocket을 연다.
DatagramSocket datagramSocket = new DatagramSocket(포트번호);

//[2] 패킷을 받을 배열과 길이를 지정한다.
DatagramPacket datagramPacket = new DatagramPacket(받은 배열을 저장할 바이트 배열,배열의 길이);

//[3] 패킷을 받는다.
datagramSocket.receive(datagramPacket);

//[4] 소켓을 닫는다.
datagramSocket.close();

 

[연습 예제_간단한 데이터 송수신]

<Client>

package udpProtocol;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Client {

	public static void main(String[] args) throws Exception{
		//[1] 데이터그램 소켓으로 가야하는 곳을 지정
		DatagramSocket datagramSocket = new DatagramSocket();
		InetAddress ia = InetAddress.getByName("localhost");
		
		for(int i = 1; i <= 3; i++) {
			//[2] 데이터그램 패킷으로 데이터를 묶어둔다. 
			String data = "데이터"+i;
			byte[] byteArr = data.getBytes("UTF-8");
			DatagramPacket datagramPacket = new DatagramPacket(
				byteArr, byteArr.length,ia,8000
			);	
			
			//[3] 패킷을 소켓을 통해 전송한다.
			datagramSocket.send(datagramPacket);
			
		}//end for
		
		//[4] 소켓을 닫는다.
		datagramSocket.close();
		
	}//end main

}

<Server>

package udpProtocol;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Server {

	public static void main(String[] args) throws Exception{
		//[1] 소켓을 연다.
		DatagramSocket datagramSocket = new DatagramSocket(8000);
		
		//[2] 패킷 단위로 데이터를 받는다.
		//쓰레드를 형성해서 무한 루프로 데이터를 받는다.
		Thread thread = new Thread() {
			@Override
			public void run() {
				System.out.println("수신 시작");
				try {
					while(true) {
						DatagramPacket packet = new DatagramPacket(new byte[100],100);
						datagramSocket.receive(packet);
						String data = new String(packet.getData(),0,packet.getLength(),"UTF-8");
						System.out.println("[받은 내용 : "+packet.getSocketAddress()+"]"+data);
					}
				} catch (IOException e) {
					System.out.println("[수신 종료]");
				}
			}
		};//end thread
		
		thread.start();
		
		Thread.sleep(10000);
		datagramSocket.close();
	}//end main

}

>> 수신 결과

수신 시작
[받은 내용 : /127.0.0.1:55273]데이터1
[받은 내용 : /127.0.0.1:55273]데이터2
[받은 내용 : /127.0.0.1:55273]데이터3
[수신 종료]

 

[참조]

- 자바의 정석, 남궁성 지음

- 이것이 자바다

- 코딩하는 거니

- 티스토리 블로그 

- 그 외 : 국비지원 수업 내용 참조

1. 스택과 큐

https://www.youtube.com/watch?v=ktvhRSRohR4 

▶ 스택(Stack) : 밑이 막힌 상자

   - LIFO구조. Last in First Out / push(저장) & pop(추출) 방식

   - 배열이 적합   *순차적인 추가/삭제

▶ 큐(Queue)  : 양끝이 뚫린 상자(포장마차의 종이컵 빼는 것과 같다)

   - FIFO구조. First in First Out / otter(저장, 제공한다) & poll(추출) 

   - 링크드리스트가 적합   *비순차적인 추가/삭제

 

■ 스택의 메소드 **JAVA에서 스택은 클래스 (객체생성 가능)

push(Object) : Object  --- Stack객체에 item을 저장

pop( ) : Object      ---  맨 위의 것 꺼내기

empty( ) : boolean ---  비어있는지

peek(  )  : Object   ---  맨 위의 것 읽기 (꺼내지X)

search(Object) : int ---  맨 위에서 1부터시작해서 순서 반환 *못찾으면 -1 반환

 

■ 큐의 메소드  **JAVA에서 큐는 인터페이스 (객체생성 불가능)

offer(Object) : boolean  --- Queue 객체에 item을 저장(예외 발생X)

poll( ) : Object      ---  객체를 꺼내서 반환(예외 발생X)

peek(  )  : Object   ---  삭제 없이 요소 읽음(꺼내지X)

add(Object) : boolean  --- Queue 객체에 item을 저장(예외 발생O)

remove() : Object  ---  객체를 꺼내서 반환(예외 발생O)

   [ 큐 사용법]
   1. 큐를 직접 구현
   2. 큐를 구현한 클래스를 사용 >> Java API 중 Queue를 구현한 목록 확인 (LinkedList도 큐 구현)
      Queue q = new LinkedList();

 

1. ArrayList : 배열 기반 리스트

https://www.youtube.com/watch?v=_2e-cgwMOyc 

▶ Vector를 개선. *차이점) Vector는 동기화 가능/ ArrayList는 동기화X

▶ 생성자

ArrayList()  
ArrayList(Collection c) 컬렉션을 넣으면 배열리스트로 변경됨
ArrayList(int initalCapacity) 저장하려는 갯수만큼 길이 지정

* 저장갯수를 지정해주지 않으면 배열이 늘어나고 줄어들 때마다 배열이 새로 생성되기에 성능 떨어진다.

▶ 메소드

추가 삭제 검색 기타
add(Object o) : boolean
add(int index, Object element) 
addAll(컬렉션)
addAll(index, 컬렉션)
remove(Object o) : boolean
remove(int index)
removeAll(Collection c)
clear()
indexOf() : int  <- index
lastIndexOf() : int
contains()
get(int index) : Object
set(index, Object) : Object
subList()
toArray() : Object[]
isEmpty()
trimToSize() - 빈공간제거
size() - 갯수 반환

▶ ArrayList에서 객체를 추가하거나 삭제할 때 배열의 복사가 이루어질 수 있다.

    ★ 삭제할 때, Last in First Out 방식을 취할 경우, 배열 복사가 발생하지 않는다. (성능 ↑)

 

[예제 연습1]

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ArrayListEx2 {

	public static void main(String[] args) {
		final int LIMIT = 10;
		String source = "0123456789abcdefghijABCDEFGHIJ!@#$%^&*()ZZZ"; 
		int length = source.length(); 
		
		List list = new ArrayList(length/LIMIT+10);
		
		for(int i = 0; i < length; i+=LIMIT) {
			if(i+LIMIT < length)
				list.add(source.substring(i,i+LIMIT));
			else
				list.add(source.substring(i));
		}
		
		for(int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		
	}//end main
}//end class

>> 결과

0123456789
abcdefghij
ABCDEFGHIJ
!@#$%^&*()
ZZZ

 

2. LinkedList 

https://www.youtube.com/watch?v=1ey5QpqbapU 

[배열의 장단점]

- 장점 : 배열의 구조가 간단하고, 데이터를 읽는데 걸리는 시간이 짧다. 

- 단점1 : (실행중) 크기를 변경할 수 없다. (크기를 변경할 경우 : 크기를 늘려 복사해서 참조변경)

         * 크기 변경을 피하기 위해 충분히 큰 배열을 생성하면, 메모리가 낭비됨

- 단점2 : 비순차적인(=중간에) 데이터의 추가, 삭제에 시간이 많이 걸린다. 

         * 데이터를 추가/삭제하려면 다른 데이터를 옮겨야함

         * 순차적인 데이터 추가(끝에 추가)와 삭제(끝부터 삭제)는 빠르다.

[LinkedList <- 배열의 단점을 보완]

- 배열과 달리, 링크드 리스트는 불연속적으로 존재하는 데이터를 연결

▶ 데이터의 삭제 : 단 한 번의 참조 변경으로 가능

▶ 데이터의 추가 : 한 번의 객체 생성과 두 번의 참조변경만으로 가능

- 단점 : 데이터 접근성이 나쁘다 (why? 노드들이 next로 하나씩 연결되어 있음)

- 개선한 것

▶ 더블리 링크드 리스트 : 이중 연결리스트 *하나의 노드에 next + previous

▶ 더블리 써큘러 링크드 리스트 : 이중원형 연결리스트 *첫번째->맨끝 / 맨끝->첫번째 연결

- 자바는 더블리 링크드 리스트를 사용한다.

 

ArrayList vs LinkedList 비교

그림으로 보는 ArrayList와 LinkedList의 비교

  특징 읽기(접근시간) 추가/삭제 비고
ArrayList 연속적 빠르다 느리다 순차적인 추가삭제는 더 빠르다.
비효율적인 메모리사용
LinedList 불연속 느리다 빠르다 데이터가 많을수록 접근성이 떨어진다.

 

▶ 들어가기 전에..

   컬렉션의 대부분의 내용은 자바의 정석 강의을 보고 공부하고 있습니다.
   영상 내용 중 중요한 것을 작성했으나 제가 쓴 부분이 오류가 있을 수 있으니 오류가 있으면 댓글 부탁드립니다.

 

1. 컬렉션 프레임웍(Collection Framework)의 이해

https://www.youtube.com/watch?v=z9GpUGoYCw4

■ 용어 

▶ 컬렉션 (모아놨다)

▶ 프레임웍(정형화된 틀) : 라이브러리 + 프로그래밍 방식

    *라이브러리 : 다른 사람이 이미 만들어 놓은 걸 모아논 곳(라이브러리=도서관). 기능만 제공한다(ex. JavaAPI)

▶ 컬렉션 프레임웍 : 다수의 객체를 다루기 위한 표준화된 프로그래밍 방식 

    *객체 = 데이터 

    - java.util 패키지에 포함. (JDK2.0부터)

▶ 컬렉션 클래스

 

■ 컬렉션 프레임웍의 핵심 인터페이스

공통 인터페이스 순서 중복
Collection List O O 대기자 명단(1.홍길동/2.김길동...)
Set(집합) X X 네 발 동물 집합, 양의 정수 집합 
- Map X 키X, 값O 우편변호, 지역변호(전화번호), 아이디/패스워드

 

2. Collection인터페이스의 메소드

https://www.youtube.com/watch?v=RscGmop2Bzo 

■ Collection 인터페이스 _ 검색/추가/삭제/기타

  메소드 설명
검색 boolean contains(Object o)
boolean containsAll(Collection c)
지정된 객체가 있는지 확인
지정된 컬렉션의 객체들이 있는지 확인
추가 boolean add(Object o)
boolean addAll(Collection c)
지정된 객체 추가
지정된 컬렉션의 객체들을 추가
삭제 boolean remove(Object o)
boolean removeAll(Collection c)
boolean retainAll(Collection c)
void clear()
지정된 객체 삭제
지정된 컬렉션에 포함된 객체들을 삭제
지정된 컬렉션 외의 객체를 삭제
컬렉션의 모든 객체 삭제
기타 int size()
boolean isEmpty()
Iterator iterator()
Object[] toArray()
Object[] toArray(Object[] a)
컬렉션에 저장된 객체의 갯수를 반환
컬렉션이 비어있는지 확인
컬렉션의 iterator를 얻어서 반환
컬렉션에 저장된 객체를 Object타입 객체배열로 반환
컬렉션에 저장된 객체를 저장해서 반환

 

■ List 인터페이스(순서O/중복O) _ 검색/추가/삭제/읽기/변경/추출/정렬

  메소드 설명
검색 int indexOf(Object o)
int lastIndexOf(Object o)
지정된 객체의 위치를 첫번째부터 찾아 반환
지정된 객체의 위치를 마지막부터 찾아 반환
추가 void add(int index, Object element)
boolean addAll(int index, Collection c)
지정된 위치에 객체를 추가
지정된 위치에 컬렉션에 있는 객체를 추가
삭제 Object remove(int index) 지정된 위치의 객체 삭제
읽기 Object get(int index) 지정된 위치에 있는 객체를 반환
변경 Object set(int index, Object element) 지정된 위치에 객체를 저장
추출 List subList(int fromIndex, int toIndex) 지정된 범위부터의 객체를 List로 반환
정렬 void sort(Comparator c) 지정된 비교자로 List를 정렬

 

■ Set 인터페이스(순서X/중복X)_메소드는 컬렉션과 동일+집합 관련 메소드

- addAll(Collection c) : boolean [합집합]

- containsAll(Collection c) : boolean [부분집합]

- removeAll() [차집합]

- retainAll() [교집합]

 

■ Map 인터페이스(순서X/중복-키X,값O)

  메소드 설명
검색 boolean containsKey(Object key)
boolean containsValue(Object value)
Object get(Object key)
key가 있는지 확인
value가 있는지 확인
key를 가진 객체 반환
추가 Object put(Object key, Object value)
void putAll(Map t)
Map에 value객체를 key객체에 맵핑해서 저장
Map에 모든 key-value쌍 추가
삭제 Object remove(Object key) key를 가진 key-value삭제
읽기 Set keySet()
Set entrySet()
Collection values()
모든 key객체 반환
모든 key-value쌍을 Map.Entry형식으로 하여 Set로 반환
모든 value객체 반환

 

>> 실행결과

차수 : 5
---snail1---
[   1   2   3   4   5]
[  16  17  18  19   6]
[  15  24  25  20   7]
[  14  23  22  21   8]
[  13  12  11  10   9]
---snail2---
[  25  24  23  22  21]
[  10   9   8   7  20]
[  11   2   1   6  19]
[  12   3   4   5  18]
[  13  14  15  16  17]
또?(y/n) : n
----END----

[Snail 객체]

package myutil;

public class Snail {
	//Right -> Down -> Left -> Up
	//이 과정을 반복하되,
	//만약 움직이려는 방향에 값이 있을 경우, 현재 자리에서 이동하지 않고,
	 //값을 넣지 않고 방향을 전환한다.
	//Right : col++
	//Down : row++
	//Left : col__
	//Up : row--
	
	//이동 정보에 대한 상수 선언
	public static final int RIGHT = 1;
	public static final int DOWN = 2;
	public static final int LEFT = 3;
	public static final int UP = 4;
	
	//현재 이동 방향 정보를 저장할 변수
	int direction;
	
	int chasu;	
	int[][] snail_array;
	
	public void setChasu(int chasu) {
		this.chasu = chasu;
		
		System.out.println("---snail1---");
		
		//달팽이 만들기
		make_snail();
		
		//출력
		display();
		
		System.out.println("---snail2---");
		
		//달팽이 만들기
		make_snail2();
		
		//출력
		display();
	}
	
	private void make_snail() {
		//달팽이 배열 생성
		snail_array = new int[chasu][chasu];
		
		int row = 0;
		int col = -1;
		int su = 1;
		
		direction = RIGHT;
		
		//[0][0]부터 채워나가기
		for(int i = 0; i < chasu*chasu; i++) {
			if(direction == RIGHT) { //오른쪽 채우기
				col++;
				if(col == chasu || snail_array[row][col]!=0) {//이동하다 막히면
					row++;
					col--;
					direction = DOWN;
				}
			}else if(direction == DOWN) { //아래쪽 채우기
				row++;
				if(row == chasu || snail_array[row][col]!=0) {
					row--;
					col--;
					direction = LEFT;
				}
			}else if(direction == LEFT) { //왼쪽 채우기
				col--;
				if(col < 0 || snail_array[row][col]!=0) {
					row--;
					col++;
					direction = UP;
				}
			}else if(direction == UP) {//위쪽 채우기
				row--;
				if(snail_array[row][col]!=0) {
					row++;
					col++;
					direction = RIGHT;
				}
			}
			
			snail_array[row][col] = su++;
		}//end for()
	}//end snail()
	
	private void make_snail2() {
		//달팽이 배열 생성
		snail_array = new int[chasu][chasu];
		
		int row = 0;
		int col = -1;
		int su = chasu*chasu;
		
		direction = RIGHT;
		
		//[0][0]부터 채워나가기
		for(int i = 0; i < chasu*chasu; i++) {
			if(direction == RIGHT) { //오른쪽 채우기
				col++;
				if(col == chasu || snail_array[row][col]!=0) {//이동하다 막히면
					row++;
					col--;
					direction = DOWN;
				}
			}else if(direction == DOWN) { //아래쪽 채우기
				row++;
				if(row == chasu || snail_array[row][col]!=0) {
					row--;
					col--;
					direction = LEFT;
				}
			}else if(direction == LEFT) { //왼쪽 채우기
				col--;
				if(col < 0 || snail_array[row][col]!=0) {
					row--;
					col++;
					direction = UP;
				}
			}else if(direction == UP) {//위쪽 채우기
				row--;
				if(snail_array[row][col]!=0) {
					row++;
					col++;
					direction = RIGHT;
				}
			}
			
			snail_array[row][col] = su--;
		}//end for()
	}

	public void display() {
		for(int i = 0; i < chasu; i++) {
			System.out.print("[");
			for(int j = 0; j < chasu; j++) {
				System.out.printf("%4d",snail_array[i][j]);
			}
			System.out.print("]");
			System.out.println();
		}//end for()
	}
}//end Snail

[Main 함수]

package mymain;

import java.util.Scanner;
import myutil.Snail;

public class _11_Question_Snail {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int chasu;
		String yn = "y";
		Snail snail = new Snail();
		
		while(true) {
			System.out.print("차수 : ");
			chasu = scanner.nextInt();
						
			//달팽이 객체 - 차수 전달(setter)
			snail.setChasu(chasu);
			//달팽이 출력
			
			//또?
			System.out.print("또?(y/n) : ");
			yn = scanner.next();
			if(!yn.equalsIgnoreCase("y")) break;
		}//end while
		
		System.out.println("----END----");
		scanner.close();
	}//end main
	
}
package mymain;

import java.util.Arrays;

public class _10_Question_Mabanjin {
	public static void main(String[] args) {
		/*
		[마방진 원리]

		대각선으로 이동하라(plus -1 on row +1 on col)

		만약 바둑판의 행과 열을 모두 벗어날 경우(row<0,col>Max) 자기자신의 아래로 가라
		그렇지 않고 바둑판의 행을 벗어날경우(row<0) row의 가장 아래로 가라
		그렇지 않고 열을 벗어날 경우(col>Max), col의 가장 왼쪽으로 가라 
		그렇지 않고 (대각선 이동은 가능하나) 그 자리에 다른 값이 있을 경우 자기 자신의 아래로 가라 
		
		해당 위치에 다음 숫자를 넣어라
		
		*/
		int[][] testArr = new int[5][5];
		Mabanjin.makeStartPoint(testArr);
		for(int i = 0; i < testArr.length; i++) {
			System.out.println(Arrays.toString(testArr[i]));
		}
		System.out.println();
		Mabanjin.mabanjin(testArr);
		for(int i = 0; i < testArr.length; i++) {
			System.out.println(Arrays.toString(testArr[i]));
		}
	}
	
}

class Mabanjin{
	public static void makeStartPoint(int[][] arr) {
		//배열 값 초기화, 시작 포인트 1로 잡기
		for(int i = 0; i < arr.length; i++) {
			Arrays.fill(arr[i], 0);
		}
		arr[0][arr[0].length/2] = 1;
	}
	public static int[][] mabanjin(int[][] arr) {
		final int ROW_MAX = arr.length;
		final int COL_MAX = arr[0].length;
		
		//배열 안에 넣을 리터럴(1부터 ~ n)
		int n = 1;
		
		//이동 포인트
		int r = 0;
		int c = arr[0].length/2;
		
		for(int i = 0; i < ROW_MAX*COL_MAX-1; i++) {
			r -= 1;
			c += 1;
			if(r < 0 && c > COL_MAX-1) {
				r = r + 2;
				c = c - 1;
			}else if(r < 0) {
				r = r+ROW_MAX;
			}else if(c > COL_MAX-1) {
				c = COL_MAX-c;
			}else if(arr[r][c] > 0) {
				r = r + 2;
				c = c - 1;
			}
			
			arr[r][c] = ++n;
			
		}
		
		return arr;
	}
	
}

>> 실행결과

[0, 0, 1, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]

[17, 24, 1, 8, 15]
[23, 5, 7, 14, 16]
[4, 6, 13, 20, 22]
[10, 12, 19, 21, 3]
[11, 18, 25, 2, 9]

+ Recent posts