18日目のコンセントと流れにしました!


//		--------------------- accept() 메소드로 서버내 연결소켓 생성 --------------------------------
		
		
		ServerSocket serverSocket = new ServerSocket(listenPort,backLog,InetAddress.getLocalHost()); 
		
	
		log.info("1.serverSoket : {}",serverSocket); 
	
		
//		try(serverSocket){  // ()안에, 반드시 close 해야할 자원객체를 참조변수를 넣어라!!!
//			// 이 블록안에서 , 무언가 수행하다가 예외가 발생하면 커버해준다.
//			
//			// 이 블록 안에서 serverSocket 에 저장된 자원객체를 사용하는 곳 
//		} // try -with- resources 
		
		
//		serverSocket.close(); //자원해제: 중간에 오류가 나면 이것이 실행안된다. 따라서 try를 씀
		
		
		
//		-----
		//ServerSocket, Socket 자원 객체라고 부름 인터넷을 통해 사용하기 때문에 
		
		try(serverSocket) { 
		
			log.info("2.server listening on port {} and addr {} ...", listenPort, serverSocket.getInetAddress());
			
			while (true) { //서버 쪽에 생긴 소켓에 대한 정보를 얻는 것 
				
				Socket socket = serverSocket.accept(); // Block I/O // 서버쪽에 클라이언트와 연결할 새로운 소켓을 만든다.
				
				try(socket){
					
					log.info("3.socket : {}", socket); //나의 소켓 ip주소 포트번호 
					log.info("\t+ getInetAddress: {} , getport:{}, getLocalport:{}" , 
							socket.getInetAddress(), socket.getPort(), socket.getLocalPort());
					//내 꺼를 끌어내고 싶을 때 socket.getInetAddress(), socket.getPort() 쓴다.
					log.info("\t + getRemoteSocketAddress: {}" , socket.getRemoteSocketAddress()); //클라이언트의 소켓 주소를 알고 싶다 할 때 
					
					
				}//try - with - resources
					
			} // while
		
		} //try - with - resources
		
		
		
//telnet으로 내 아이피와 포트번호를 통해 접근한 결과
//18:16:53.120 DEBUG --- [main           ] i.ServerSocketEx.(main:16) │ main([]) invoked.
//18:16:53.126  INFO --- [main           ] i.ServerSocketEx.(main:51) │ 1.serverSoket : ServerSocket[addr=DESKTOP-V17RG1U/1.1.1.1(임의),localport=7777]
//18:16:53.126  INFO --- [main           ] i.ServerSocketEx.(main:70) │ 2.server listening on port 7777 and addr DESKTOP-V17RG1U/1.1.1.1(임의) ...	18:17:43.017  INFO --- [main           ] i.ServerSocketEx.(main:78) │ 3.socket : Socket[addr=/1.1.1.1(임의),port=51923,localport=7777]
//18:17:43.017  INFO --- [main           ] i.ServerSocketEx.(main:79) │ 	+ getInetAddress: /1.1.1.1(임의) , getport:51923, getLocalport:7777
//18:17:43.018  INFO --- [main           ] i.ServerSocketEx.(main:82) │ 	 + getRemoteSocketAddress: /1.1.1.1(임의):51923
		
		
		
		

	} //main 


}// class end
次のコードはソケットで接続されたクライアントとの情報のやりとりの例であり,Java I/Oがわからないと理解できない.
package inetex01;

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.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;

import lombok.extern.log4j.Log4j2;

@Log4j2
public class SingleThreadSoketServerEx {
	
	private static final int CR = 13; 
	private static final int LF = 10;
	
	
	public static void main(String[] args) throws IOException {
		log.info("main({}) invoked." , Arrays.toString(args));
		
		int listenport = 7777;
		int backLog = 100;
		
//    ----------------------------------------
		
		//  Listen Port 만 지정하면, 서버pc의 모든 ip 주소를 이용해서 연결요청을 받아 들이는 "IP ANY" 가 된다.
		ServerSocket serverSock = new ServerSocket(listenport, backLog); //서버소켓 형성 세부사항 설정 
		log.info("1. serverSock : {}" , serverSock);

//	    ----------------------------------------
		
		
		try(serverSock) { // try - with - resources block 
			
			while(true) { // Infinite loop
				
				log.info("=========================================================");
				log.info("2. listening on port {} and addr {} ... " , listenport , serverSock.getInetAddress());
				log.info("=========================================================");
				
				serverSock.setSoTimeout(0);
//				serverSock.setSoTimeout(5*1000);
				
				Socket sock =serverSock.accept(); //연결받는 어셉트
				
				log.info("3.Client Connected");
				log.info("\t3-1. sock: {}", sock);
				log.info("\t3-1. getLocalSocketAddress(): {}", sock.getLocalSocketAddress());
				log.info("\t3-1. getRemoteSocketAddress(): {}", sock.getRemoteSocketAddress());
				
				
				
				// 아래의 코드부터는 "자바 입출력(JAVA I/O API)"를 모르고서는 할 수 가 없답니다
				// -------------------------------------------------------------------
				// 1. RECV - Socket 으로 연결된 클라이언트로부터, 데이터를 수신하자 !
				// ------------------------------------------------------------------
				
				
				String recvLine = null; 
				String sendLine = null; 
				
				try(sock) {
					
					try {
						
						InputStream is = sock.getInputStream();
						BufferedReader br = new BufferedReader(new InputStreamReader(is));
					
						recvLine = br.readLine();
					
						log.info("\t3-4. reacvLine : {}", recvLine);
						
					} catch(Exception e) {
						log.error("\t* Exception : {} - {}", e.getClass().getName(), e.getMessage());
					} finally {
						sock.shutdownInput();
					} // try- catch - finally
					
					
					
				
				
				
				
				// 
				// -------------------------------------------------------------------
				// 2. SENT - Socket 으로 연결된 클라이언트에게, 데이터를 보내자 !
				// ------------------------------------------------------------------
				
				
				
					try {
						sendLine = recvLine ;
						
						OutputStream os = sock.getOutputStream();
						
						BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
						
						
						bw.write(sendLine);
						bw.write(CR);
						bw.write(LF);
						
						bw.flush();
						
						log.info("\t3-5. sendLine : {}",sendLine);
					
					} catch(Exception e) {
						log.error("\t* Exception : {} - {} ", e.getClass(),e.getMessage());
					} finally {
						sock.shutdownOutput();
					}//try - catch- finally
					
					log.info("4. Client Disonnected.");
					
				}// try - with - resources : sock
			}//while
		}// try - with - resources : 'serverSocket'
		
		

		
		
		
	}//main 

}// class
そこで、入出力の勉強を始めます.しかし、入る前にtry-with-resources文と自動梱包を学びました.
---------------------------------<오토-박싱,언박싱>------------------------------------------

package inetex01;

public class ttt2 {
	
	//Auto-boxing / Auto - unboxing
	public static void main(String[] args) {
		
		byte b = 10; 
		
//		Byte byteObj = new Byte(b);  -> 취소선 : Deprecated 더 이상 사용하지 말라
	
		Byte byteObj= 10; //Auto-boxing 참조타입의 빠이트에 기본타입 10 넣기 ;
		b = byteObj; // Auto-boxing 참조타입 빠이트 값을 바이트에 넣기 
		// 다 컴파일러가 알아서 변환해서 넣어주니 래퍼클래스와 기본타입을 고민하지말라
		
		double d = 3.141592;
		Double dd = d;
		d = dd;

// -------------------------------String타입 값을 바꾸는 법!
//		byte bValue = Byte.parseByte("1"); //  래퍼클래스.parse래퍼클래스()-  기본타입값으로 바꿔준다
//		Byte byteObj2 = Byte.valueOf("10"); //  래퍼클래스.valueOf() - 래퍼타입 값으로 담어준다.
//		System.out.println(bValue);
		
// -------------------------------
		String age = "101" ;
		byte bValue = Byte.parseByte(age);
		Byte byteObj2 = Byte.valueOf(age);
		System.out.println(bValue +"/"+ byteObj2 );
		
	}//main
} // class end 
-------------------------------<try-with-resources>---------------------------------------

package inetex01;

public class ttt {
	
	
	// try -with - resources block을 이용하면, 예외발생여부와 상관없이 
	// 안전하게 자원객체(들)을 close 할 수 있다. 
	public static void main(String[] args) throws Exception {
		UserDefinedResource1 resource1 = new UserDefinedResource1();
		UserDefinedResource2 resource2 = new UserDefinedResource2();
		UserDefinedResource3 resource3 = new UserDefinedResource3();
		
		// ... 위 3개의 자원객체를 잘사용 하였다고 가정하고 ....
		// 예외발생코드를 일부러 넣음 .. 예외 때문에 아래의 close메소드들이 작동이 안됌. 
//		String movie = "삼백";
//		int i300 = Integer.parseInt(movie);
//		System.out.println("i300:"+ i300);

		
//		resource1.close();
//		resource2.close();
//		resource3.close();
		
		
		
//		따라서 try에 예외처리를 맡겨준다.
		
// 자바 7까지는 이렇게 해야함 
//		try( 
//		UserDefinedResource1 resource1 = new UserDefinedResource1();
//		UserDefinedResource2 resource2 = new UserDefinedResource2();
//		){

		
		try(resource1; resource2; resource3;){ // 자바 최근거는 이렇게 
			//  try는 오른쪽에서 왼쪽으로 실행되고 닫음 
			String movie = "삼백";
			int i300 = Integer.parseInt(movie);
			System.out.println("i300:"+ i300);

			resource1.close();
			resource2.close();
			resource3.close();
		} // try - with - resources
		
		
		
		
	}//main
	
 }  //end class


class UserDefinedResource1 implements AutoCloseable {

	@Override
	public void close() throws Exception {
		System.out.println("UserDefinedResource1::close() invoked");
		
	}// close
	
} // end class

//------------------------------------------------------------------------------
class UserDefinedResource2 implements AutoCloseable {

	@Override
	public void close() throws Exception {
		System.out.println("UserDefinedResource2::close() invoked");
		
	}// close
	
} // end class

//----------------------------------------------------------------------------------------
class UserDefinedResource3 implements AutoCloseable {

	@Override
	public void close() throws Exception {
		System.out.println("UserDefinedResource3::close() invoked");
		
	}// close
	
} // end class

入力ストリームと出力ストリーム


-プログラム入力、出力、出力
-出力到達ディスプレイ(ファイル、プログラム)
-入力の開始点はキーボード(ファイル、プログラム)

Streamとは?


データ・フロー
したがって、あるプログラムでは、出力ストリームが別のプログラムで流れるだけで、入力ストリームは別のプログラムで流れる.

文字の流れ


-文字ストリームに基づいて入力および出力される文字ストリーム
-テキストのみを送信および受信できます(ex>Textファイル)

バイトベースのストリーム


-バイトベースの整数入力および送信時のバイトストリーム
-画像、マルチメディア文字などすべてのタイプのデータを受信および送信するバイナリ・ファイル.
-バイトベースのファイル読み取り可能文字なし
効率的なので、バイトストリームで処理するのではなく、文字ベースのストリームがあります.

java.ioパッケージ


-Javaの基本データI/O(IO:Input/Output)APIを提供する

バイトベースのストリーム


トップレベルの入力ストリームInputStream


-バイトベースの入力ストリームとして抽象化された最上位クラス
-InputStreamクラスに依存しない主な方法(read()、close()<--tryブロック)
----------------------------------------<매개변수없는read()>-----------------------------------
package thisjava;

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

public class ReadEx1 {
	// 바이트 기반 파일 입력 스트림을 통해서, 파일의 데이터를 read 하자!!
	public static void main(String[] args) throws Exception {
		// 바이트기반의 파일 입력스트림 객체 생성
		InputStream is = new FileInputStream("c:/Temp/TTT.java"); // 다형성-1 파일을 들여오는 스트림 객체생성
		
		int readByte; // 실제 입력스트림에서 read한 바이트 개수를 저장하는 변수 
		
		while(true) {
			readByte = is.read(); // 입력 스트림으로부터 1바이트를 읽고 읽은 바이트 리턴해서 변수에 저장
			if(readByte == -1) {  // 파일의 끝 (EOF, End - Of- File)을 만나면 (-1)
				break; 			  // 무한루프 탈출 파일을 읽는 것을 멈춤
			}// if
			System.out.println(readByte); // 
			System.out.print((char)readByte  + "--"); // 실제 읽어낸 1 바이트를 문자로 변환  
		}//while
		
		is.close(); // 자원객체는 다 사용하고 나면 반드시 닫자 !
			
	} // main

}//end class

//결과

//ã--„--±--ã--„--´--ã--„--·--ã--„--¹--
//--
//--p--u--b--l--i--c-- --c--l--a--s--s-- --T--T--T--{--
//--
//--	--p--u--b--l--i--c-- --s--t--a--t--i--c-- --v--o--i--d-- --m--a--i--n--(--S--t--r--i--n--g--[--]-- --a--r--g--s--)--{--
//--
//--
//--
//--	--
//--
//--
//--
//--	--S--y--s--t--e--m--.--o--u--t--.--p--r--i--n--t--l--n--(--"--H--e--l--l--o--.-- --J--A--V--A--!--!--"--)--;--
//--
//--
//--
//--	--}--/--/--m--a--i--n--
//--
//--
//--
//--
//--
//--
//--
//--}--/--/-- --e--n--d-- --c--l--a--s--s--
//--
//--
//--
//--
//--
//--c--l--a--s--s-- --T--e--m--p-- --{-- --
//--
//-- --;--;--
//--
//--}--/--/--e--n--d-- --c--l--a--s--s--
----------------------------<스트림에서 읽은 바이트를 배열로 담아내는 예제>--------------------------
package thisjava;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Arrays;

public class ReadEx2 {
	// 바이트 기반 파일 입력 스트림을 통해서, 파일의 데이터를 read 하자!!
	public static void main(String[] args) throws Exception {
		// 바이트기반의 파일 입력스트림 객체 생성
		InputStream is = new FileInputStream("c:/Temp/TTT.java"); // 다형성-1
		
		
		
		try(is){
			// is 라는 자원객체를 사용하는 실행문자들을 다 넣음.
			int readByteNo; 
			
			byte[] readBytes =new byte[3]; // 실제 입력스트림에서 read한 바이트 개수를 배열로 담아내는 변수
			//(바이트의 양이 많을 때는 read(byte[] b) 메서드를 사용하는 것이 좋음.)
			
			
			while(true) {
				// 바가지로 읽어내면, 실제로 스트림에서 읽어낸 바이트 개수를 반환
				readByteNo = is.read(readBytes); //바가지로 읽어내자!
				if(readByteNo == -1) {  // 파일의 끝 (EOF, End - Of- File)을 만나면 (-1)
					break; 			  // 무한루프 탈출
				}// if
				
				// 바가지의 바이트 배열을 문자열로 변환하여, 누적(연결)
				
				System.out.print(new String(readBytes, 0, readByteNo)+"--");
			}//while

		}//try -with -resources
	} // main

}//end class


// 결과 
//ㄱ--ㄴ--ㄷ--ㄹ--
//p--ubl--ic --cla--ss --TTT--{
//--	pu--bli--c s--tat--ic --voi--d m--ain--(St--rin--g[]-- ar--gs)--{
//--
//	--
//
//--
//	S--yst--em.--out--.pr--int--ln(--"He--llo--. J--AVA--!!"--);
//--
//
//--	}/--/ma--in
//--
//
//--
//
//--
//}/--/ e--nd --cla--ss
//--
//
//--
//c--las--s T--emp-- { --
// --;;
//--
//}/--/en--d c--las--s--
------------------<스트림에서 읽은 바이트를 배열에 들어갈 공간을 정해놓고 집어넣는 예제>------------------
package thisjava;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Scanner;

import lombok.Cleanup;

public class ReadEx3 {
	// 바이트 기반 파일 입력 스트림을 통해서, 파일의 데이터를 read 하자!!
	public static void main(String[] args) throws Exception {
		// 바이트기반의 파일 입력스트림 객체 생성
		@Cleanup
		InputStream is = new FileInputStream("c:/Temp/TTT.java"); // 다형성-1
		
		
		int readByteNo; 
		
		// 바가지의 사용법 
		byte[] readBytes =new byte[4]; 

		
		readByteNo = is.read(readBytes, 1, 2); //바가지의 일부만 사용 
        
		System.out.println(Arrays.toString(readBytes));


	
	
		
			
	} // main

}//end class

トップレベル出力ストリームOutputStream


-バイトベースの出力ストリームとして抽象化された最上位クラス
-OutputStreamの主な方法
------------------------------<반복문으로 하나씩 반복해서 출력>--------------------------
package thisjava;

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

public class WriteEx1 {
	//지정된 경로의 파일에 문자열을 출력해보자!
	public static void main(String[] args) throws Exception{
		OutputStream os =new FileOutputStream("C:/Temp/test.txt");
		
		// String -> byte[]로 변환 (왜? 바이트 기반이니까 ..)
		byte[] data = "ABC".getBytes(); // 1.
		
		for(int i = 0 ;  i<data.length; i++) {
			os.write(data[i]);  				// 바가지 쏟아붇기
		
		
		
		}//for
		
		
		
		
		
		//자원객체를 닫기 전에 반드시 최소 한번은 수행해야함!
		os.flush();  		//출력 버퍼에 남아있는 강제출력
//							출력스트림에는 버퍼가 있다.
//							8k가 채워져야 flush가 이뤄지는데 못채워지고 끝날 수 있다.

		os.close();  //출력버퍼를 파괴시킨다 자동으로 닫아주지 않는다 .
		
	}// main

}// end class
------------------------------<배열에 담아서 싹다 출력>--------------------------
package thisjava;

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

import lombok.Cleanup;

public class WriteEx2 {
	//지정된 경로의 파일에 문자열을 출력해보자!
	public static void main(String[] args) throws Exception{
		// 기존파일에 계속해서 추가해서  write 작업을 하려면,
		// 생성자의 두번째 매개변수로, true 추가하면 된다.
		@Cleanup OutputStream os =new FileOutputStream("C:/Temp/test.txt");
		
		// String -> byte[]로 변환 (바가지 준비)
		byte[] data = "대한민국".getBytes(); 
		
		// 출력버퍼(8k)에 바가지채로 쓰기수행
		os.write(data);    
		
		
		//출력스트림을 닫기전에 반드시 최소 1번은 강제 flushing 해야함
		// 왜? 출력버퍼 (8KB)에 잔류한 바이트들이 존재 할 수 있기 때문에 
		os.flush();  		//출력 버퍼에 남아있는 강제출력

		
	}// main

}// end class

文字ベースのストリーム


トップレベルの入力ストリームリーダー


トップレベル出力ストリームライタ


1つの多言語文字---->をバイトに変換するプロセスをエンコーディング->と呼びますエンコーディング
バイトを-->多言語文字に変換するプロセスを復号と呼びます.->アンチコーディング
-<ストリームから読み込まれたバイトを配列に入れるスペースを指定した例>についてはよくわかりませんので、いろいろ探して整理しました.
なぜreadメソッドにoffsetとlengthを書き込み、配列に格納される開始点と長さを調整するのか
1.開始点を別の位置に移動するか、または前後の空白バイトストリームの情報の位置に一致するように長さを決定する.
2.アレイ長を超えるエラーを回避するため
しかし、実際にはどのように使うべきか分かりません.勉強を続けます...終わりだ!