*책은 한 반정도 보왔는데. 2월달안에 나머지를 볼수 있다.
*하지만 문서를 남기면서 책을 보는게 아직 책내용을 확실히 이해하지 않은이상 힘들다 ㅠ.ㅠ
*지금은 여기서 접는것이고. 누군가 Java Network Programming을 본다면 참여하기 바란다 ^^;;
*하지만 문서를 남기면서 책을 보는게 아직 책내용을 확실히 이해하지 않은이상 힘들다 ㅠ.ㅠ
*지금은 여기서 접는것이고. 누군가 Java Network Programming을 본다면 참여하기 바란다 ^^;;
책을 보다가 웬지 적으면서 보는게 좋다는 생각이 든다.
JAVA Network Programming
JAVA Network Programming
1.2. Chapter2 자바 보안 모델 ¶
- 자바의 두가지 보안
- 본질적 성격을 띄는 로우 레벨 보안 : 네트워크를 통해서 읽혀진 바이트코드의 무결성과 관련 매우중요한 부분이긴하나 프로그래머가 직접적으로 세세하게 알필요없음
- 자원과 관련된 보안 : 자원과 관련된 보안은 로우 레벨 보안보다 좀더 프로그래머에게 직접적으로 관련되어있음 애플릿을 클라이언트로 사용할때 더 중요함 이는 애플릿이 보안 제약에 직접적으로 연관되어 있기 때문
- 그외 URL프로토콜,IP멀티캐스트,DNS,방화벽,HTTP 프록시 서버,SOCKS,방화벽 내부의 DNS에 관해 간단한 설명 나옴
- 본질적 성격을 띄는 로우 레벨 보안 : 네트워크를 통해서 읽혀진 바이트코드의 무결성과 관련 매우중요한 부분이긴하나 프로그래머가 직접적으로 세세하게 알필요없음
1.3. Chapter3 예외처리 ¶
- 보통 자바책에서 볼수있는 정도의 예외처리에 관한 설명이 나와있음
- 간단한 사용자 예외
~cpp import java.io.IOException; public class AuthException extends IOException{ //사용자 예외를 정의할때 적당한 예외 클래스의 서브클래스가 되는것이 중요한데 public AuthException(){ //네트워킹 코드에서는 IOException이 적당하다. } //당연한 얘기지만 IOException을 처리하는 다른 모든 코드에서 처리될수있다. public AuthException(String detail){ super(detail); } }
1.4. Chapter4 자바로 풀어보는 다중 쓰레딩 ¶
- 다중 쓰레딩은 자바 네트워크 프로그래밍에서 매우 중요한 부분이다. ^^;;
- 동기화(Synchronization) : 동기화란 여러 쓰레드가 동시에 작업할 떄 각 쓰레드의 작업 순서를 제어하기 위한 메커니즘이다.
- 자바에서 코드의 특정 부분을 한번에 한 쓰레드만이 접근할수 있도록 해주기위해 synchronized 문장을 사용
~cpp synchronized(anObject){ //중요한 코드들 }
- 세마포어(semaphores) : 세마포어란, 자바 객체가 아니라 특별한 형태의 시스템 객체이며, 이객체는 '얻기(get)'와 '놓기(release)'라는 두 가지 기능을 가지고 있다 한 순간에, 오직 하나의 쓰레드만이 세마포어를 얻을 수 있으며(get), 한 쓰레드가 세마포어를 가지고 있는 동안 세마포어를 얻으려고 시도한 다른 쓰레드들은 모두 대기 상태에 들어간다. 다시 쓰레드가 세마포어를 놓으면(release) 다른 쓰레드가 세마포어를 얻고(get) 다시 대기상태로 들어간다. 이런한 매커니즘을 사용하여 특정 작업을 동기화 할수있다.
- 동기화의 효율 : 대부분의 경우 동기화 작업은 매우 중요하며, 때로는 적대 생략해서는 안되는 경우도 있다. 그러나 불필요한 동기화 작업은 프로그램의 수행 성능을 떨어뜨리고, 재사용성을 감소시키며, 프로그램이 교착 상태에 빠지게 할 수도 있다.
- 자바에서 코드의 특정 부분을 한번에 한 쓰레드만이 접근할수 있도록 해주기위해 synchronized 문장을 사용
- Thread 클래스 : 보통 상속받아서 사용
~cpp public class SubThread extends Thread{ public void run(){ //쓰레드 작업 } public static void main(String[] args){ SubThread subThread = new SubThread(); subThread.start(); //쓰레드 시작 }
- Runnable 인터페이스 : Thread 클래스를 직접 상속받지 않은 클래스의 객체가 손쉽게 쓰레드를 생성할수 있도록 해줌
~cpp public class ThreadDemo implements Runnable{ protected Thread execution; public synchronized void begin(){ //동기화 if(execution == null){ execution = new Thread(this); //Runnable 인터페이스를 구현한 것을 넣어줌 execution.setPriority(Thread.MIN_PRIORITY); //우선수위를 정함 execution.start(); // 쓰레드시작 } } public synchronized void end(){ //동기화 if(execution !=null){ execution.interrupt(); //stop()을 쓰는 것은 별로 바람직하지 않다 stop()은 쓰레드가 어떤 상황에 있더라도 쓰레드를 바로 멈추어 버리기 때문에, execution = null; //쓰레드가 크리티컬 섹션을 수행하는 도중 이 메소드가 호출되는 경우,중요한 데이터에 다른 쓰레드가 영영 접근할수 없는 } //경우가 생길 수도 있다. 따라서 stop() 메소드를 사용하는 대신 쓰레드 자신의 종료상태를 인지하고, 수행을 중지하는 플래그 } //사용하는 방법이 더좋다. 가장 권장되는 방법은 위와 같은 플래그와 함께 interrupt()를 사용하는 것이다. public void run(){ try{ Thread myself = Thread.currentThread(); //현재 실행중인 쓰레드를 가져온다. while(execution == myself){ //쓰레드 작업 } }finally{ synchronized(this){ execution =null; } } }
- ThreadGroup 클래스 : 여래개의 쓰레드르 그룹으로 만들어 손쉽계 Thread를 관리
- Thread 통지(notification)메소드 : 주의해야 할 점은, 이 메소드들 호출하는 쓰레들이 반드시 synchronized 블록으로 동기화 되어야 한다는 점이다.
- wait() : notify() 메소드를 호출할 때까지 블록킹된다.
- notify() : 대기하고 있는 쓰레드중 하나를 꺠운다.
- notifyAll() : 메소드가 호출된 객체에서 대기하고 있는 모든 쓰레드들을 깨운다.
- wait() : notify() 메소드를 호출할 때까지 블록킹된다.
- 효과적인 다중 쓰레딩 : 자바에서 쓰레드를 생성하는 것은 매우 느린 작업이며 일부 자바 가상 머신은 쓰레드에 관련된 메모리 누스 때문에 고생하기도 한다. 따라서 효과적인 쓰레딩을 위해서는 새로 쓰레드르 생성하는 것 보다 이전에 생성했던 쓰레드 객체를 재사용하느 것이 좋다 진보된 형대의 자바 가상 머신에서는 시스템 레벨에서 이러한 쓰레드 재사용을 지원하기도 하지만, 이경우조차도 쓰레드를 재상용하는 방식을 사용하면 여러가지 이점을 얻을수 있다. --예제는 17장쯤에..
- ThreadGroup 클래스 : 여래개의 쓰레드르 그룹으로 만들어 손쉽계 Thread를 관리
2. PART2 스트림 ¶
- 5장 : 스트림을 소개합니다.
- 6장 : 스트림을 사용한 파일 처리 프로그램밍의 진수
- 7장 : 필터를 이용한 스트림의 확장 기법
- 8장 : API로 제공되는 스트림 필터
- 9장 : 메모리 기반의 I/O스트림
- 10장 : 문자 스트림을 사용한 개선된 I/O기법
- 11장 : 문자 스트림 필터
- 12장 : 메모리 기반의 문자 스트림
- 13장 : 파워업! 객체 스트림
2.1. Chapter5 스트림을 소개합니다 ¶
- 스트림 : 네트워크 프로그램에서 아주중요한부분
> 요책이 스트림에대해서 자세히나온다.딴데는 대충 설명하는데...;
- OutpuStream,InputStream : 모든 다른 스트림 클래스들의 수퍼클래스이다. 이 Chapter에서는 이둘 클래스 설명
- OutputStream 클래스 : OutputStream 클래스는 통신 채널로의 관문을 의미한다. 즉, OutputStream으로 데이터를 써넣으면 데이터는 연결된 통신 채널로 전송될 것이다.
~cpp import java.io.*; public class SimpleOut { //간단한 OutputStream 예제 public static void println(String msg) throws IOException{ synchronized(System.out){ //메시지를 터미널에 출력하던 도중에 다른 쓰레드에 의해 String이 출력될수 없도록 동기화처리 for(int i=0; i<msg.length(); ++i) System.out.write(msg.charAt(i) & 0xff); //16비트 유니코드로 구성된 String은 연속한 바이트로 매스킹한후 출력 System.out.write('\n'); //개행문자 출력 } System.out.flush(); //버퍼에 저장된 모든 데이커가 출력되었음을 확인하는 의미에서 스트림을 flush시킨다. } public static void main(String[] args) throws IOException { for(int i=0; i<args.length;i++){ println(args[i]); //넘겨받은 문자를 하나씩 넘김 } } }
- InputStream 클래스 : InputStream 클래스는 통신 채널로부터 데이터를 읽어 내는 관문을 의미한다. OutputStream에 의해 통신 채널로 쓰여진 데이터는 해당하는 InputStream에 의해 읽혀진다.
~cpp import java.io.*; public class SimpleIn { //간단한 InputStream 예제 public static void main(String[] args) throws IOException { byte[] buffer = new byte[8]; //작은 버퍼를 만들고 int numberRead; while((numberRead =System.in.read(buffer))>=0) //가능한 많은 양을 읽는다. EOF가 -1을 반환하면 출력한다. System.out.write(buffer,0,numberRead); } }
- OutputStream 클래스 : OutputStream 클래스는 통신 채널로의 관문을 의미한다. 즉, OutputStream으로 데이터를 써넣으면 데이터는 연결된 통신 채널로 전송될 것이다.
- 그외 뒤에서 배울 스트림들을 소개하고 있다.
2.2. Chapter6 스트림을 사용한 파일처리 프로그래밍의 진수 ¶
- 이장에서는 FileOutputStream과 FileInputStream에 관해 다루고 있다.
- 이외에 File,FileDescriptor,RandomAccessFile에 관해 간략히 나오고 파일스트림과 같이 사용하는 예제가 나온다.
- File클래스 : 시스템에 독립적인 파일의 이름을 나타내고 실제 파일에 관한 정보를 결정하는 메소드뿐만아니라, 파일의 속성을 바꾸는 메소드도 제공
- FileDescriptor클래스 : FileDescriptor 객체는 하위 레벨의 시스템 파일 설명자로의 핸들이다. 파일 설명자는 열려진 파일을 의미하며, 읽기 작업이나 쓰기 작업을 위한 현재의 파일 내의 위치와 같은 정보들을 포함한다. RandomAccessFile이나 FileOutputStream, FileInputStream을 사용하지 않고는 유용하게 FileDescritor를 생성할수 있는 방법은 없다 . --;
- RandomAccessFile클래스 : 파일스트림을 사용하지않고 파일을 쉽게 다룰수 있음 장점은 파일스트림 클래스는 순차적 엑세스만이 가능하지만 이것은 임의의 엑세스가 가능하다. 여기선 RandomAccessFile클래스랑 파일 스트림을 같이 쓰는데 RandomAccessFile의 장점을 가지고 네트워크에서도 별다른 수정없이 사용할수있다. 예제는 밑에 --;
- File클래스 : 시스템에 독립적인 파일의 이름을 나타내고 실제 파일에 관한 정보를 결정하는 메소드뿐만아니라, 파일의 속성을 바꾸는 메소드도 제공
- FileOutputStream 클래스 : 연속적인 데이터가 파일에 쓰여질수 있도록 해줌
- FileInputStream 클래스 : 연속적인 데이터를 읽을수 있게 해줌 --;
- 간단한 파일 스트림 예제
~cpp import java.io.*; public class copy { //메인 public static void main(String[] args) throws IOException { if(args.length !=2) //넘어오는 args가 파일이 원본 복사본 두개여야한다. throw ( new IllegalArgumentException ("Syntax:Copy <src> <dst>")); FileInputStream in = new FileInputStream(args[0]); //원본 파일 FileOutputStream out = new FileOutputStream(args[1]); //복사본 파일 byte[] buffer = new byte[16]; int numberRead; while((numberRead = in.read(buffer)) >=0) //파일을 버퍼에 가능한 많은 양을 읽고 읽은 양만큼 파일에 쓴다. 파일이 EOF일 때까지. out.write(buffer,0,numberRead); //여기서 0은 초기시작위치이고 파일에 쓸때마다 점점 옆으로 이동한다 --; out.close(); //close가 호출되지 않으면 FileOutputStream에 가비지 콜렉션이 일어날 때에 파일과 하부의 FileDescriptor가 자동으로 닫힌다. in.close(); //위에랑 마찬가지 } }
- 덮어쓰기(Overwriting)기능을 갖춘 FileOutputStream
~cpp import java.io.*; public class SimpleOverwritingFileOutputStream extends OutputStream { protected RandomAccessFile file; //랜덤 엑세스 파일 public SimpleOverwritingFileOutputStream(String filename) throws IOException { file = new RandomAccessFile(filename,"rw"); //RandomAccessFile은 파일이 존재하지 않으면 자동으로 파일생성 하고 그렇지 //않으면 파일을 연다 파일을 열면 포인터는 자동으로 파일의 시작부분을 가리키미로 //데이터를 쓰면 기존의 파일 내용 위에 덮어 쓰여진다. } public void write(int datum) throws IOException { /**@todo: implement this java.io.OutputStream abstract method*/ file.write(datum); } public void close() throws IOException{ file.close(); } }
- 위치 이동(Seeking)기능을 갖춘 FileOutputStream
~cpp import java.io.*; public class SeekableFileOutputStream extends FileOutputStream { protected RandomAccessFile file; public SeekableFileOutputStream(String filename)throws IOException { this(new RandomAccessFile(filename,"rw")); // 자신의 또다른 생성자에게 넘겨준다.--; } public SeekableFileOutputStream(File file) throws IOException{ this(file.getPath()); //역시 자신의 생성자를 호출함 } protected SeekableFileOutputStream(RandomAccessFile file) throws IOException{ super(file.getFD()); //FileOutputStream에다가 FileDescriptor를 인자로 념겨줌 this.file=file; } public void setPosition(long position) throws IOException{ file.seek(position); //position의 위치로 파일 포인터 위치를 변경 } public long getPosition() throws IOException{ return file.getFilePointer(); //현재 파일 포인터 위치를 돌려줌 } public long getLength() throws IOException{ return file.length(); //파일 길이를 돌려줌 } public void write(int b) throws java.io.IOException { /**@todo: implement this java.io.OutputStream abstract method*/ file.write(b); } }
- 표시/리셋(mark/reset)기능을 갖춘 FileInputStream만들기
~cpp import java.io.*; public class MarkResetFileInputStream extends FileInputStream { protected long markedPosition; //마크될 위지 protected RandomAccessFile file; //랜덤 엑세스 파일 public MarkResetFileInputStream(String filename)throws IOException { this(new RandomAccessFile(filename,"r")); //랜덤엑세스 파일을 생성해서 다른 생성자로 } public MarkResetFileInputStream(File file)throws IOException { this(file.getPath()); //파일명을 넘겨주어 위로 --; } protected MarkResetFileInputStream(RandomAccessFile file) throws IOException{ super(file.getFD()); //FileDescriptor를 넘겨주고 this.file=file; //파일을 저장해논다. 이러면 랜덤엑세스랑 FileInputStream 사용할수있다. markedPosition = -1; } public boolean markSupported(){ return true; } public void mark(int readAheadLimit){ try{ markedPosition = file.getFilePointer(); //현재위치를 기억한다. }catch(IOException ex){ markedPosition = -1; } } public void reset() throws IOException{ if(markedPosition == -1) throw new IOException("No mark set."); file.seek(markedPosition); //마크해논위치로 다시간다. } }
2.3. Chapter7 필터를 이용한 스트림 확장 기법 ¶
- 지금까지는 한 바이트나 바이트 배열정도의 읽고/쓰기를 지원하는 간단한 스트림만을 보와왔다. 이러한 수준의 통신은 필요이상으로 번거롭다. 그래서 이번장에서는 기존의 스트림의 위에 부가적인 기능을 제공할 수 있는 스트림인 스트림 필터(stream filter)에 대해 소게하곘다.
- FileterOutputStream , FilterInputStream 클래스 : 이것은 입출력 스트림 필터에 대한 템플리트로 이미 존재하는 InputStream,OutputStream에 연결해서 요구된 내용을 연결된 스트림의 메소드로 전댈해 주는것 이외의 기능은 제공하지 않는다.
- 표준 스트림 필터 :간략히 살펴본다.
- DataOutputStream과 DataInputStream : 기존의 바이트만 읽고 쓰는 스트림위에서 상위 수준의 통신이 가능하다. 예를 들어 String이나 부동점 실수와 같은 것을 통신할 수있다. 기존의 수준낮은(?) 것은 바이트 단위로 통신해야한다.
- PushbackInputStream : 입력 스트림으로 데이터의 읽기 복구 기능을 지원한다. 다시 말하면, 데이터가 입력 스트림으로 다시 넣어져서, 다음 번에 읽기를 수행할 때에 다시 읽혀질 수 있게 된다.
- SequenceInputStream : 일련의 InputStream들이 순차적으로 연결된다. 하나의 SequenceInputStream에 여러 InputStream이 연결되서 하나의 긴 InputStream처럼 보인다.
- LineNumberInputStream : LineNumberReader 클래스에 의해 쓸모가 없어진 이 스트림은 초보적인 수준으로 줄에 번호 매기는 기능을 제공한다.
- PrintStream : PrintWriter 클래스에 의해 쓸모가 없어진 이 클래스는 ASCII 텍스트 데이터의 출력기능을 제공한다.
- 스트림 필터의 사용 예제 : System.in으로 입력받는것을 BufferedInputStream필터를 거쳐서 LineNumberInputStream을 거처 DataInputStream을 거처서 DataOutputStream에 쓰여지고 BufferedOutputStream으로 버퍼링돼 한번에 출력된다. --;
~cpp import java.io.*; public class FilterTest{ public static void main(String[] args) { BufferedInputStream bufferedIn = new BufferedInputStream(System.in); //장치 입력을 버퍼 필터로 받는다. BufferedOutputStream bufferedOut = new BufferedOutputStream(System.out); //화면에 출력하기전 버퍼아웃픗스트림을 거친다. LineNumberInputStream lineNumberIn = new LineNumberInputStream(bufferedIn); //버퍼입력을 다시 라인을 붙여주는 필터가 받음 DataInputStream dataIn = new DataInputStream(lineNumberIn); //라인이 붙은 입력을 DataInputStream으로 받아서 한바이트이상을 전달함 DataOutputStream dataOut = new DataOutputStream(bufferedOut); //한바이트이상을 받음 try{ String line; while(true){ line = dataIn.readLine(); //한줄 입력을 받는다. String response = lineNumberIn.getLineNumber() + " : " + line.toUpperCase() + "\n"; //줄번호를 얻어서 붙임 대문자로 바꿈 dataOut.writeBytes(response); //BufferdOutputStream에 쓴다. if(line.equals("exit")) //exit가 들어오면 루프를나간다. break; } dataOut.flush(); //이제까지 버퍼에 모아논것을 출력한다. }catch(IOException ex){ System.err.println(ex); } } }
2.6. Chapter10 문자 스트림을 사용한 개선된 I/O 기법 ¶
- 지금까지는 바이트 스트림을 주로 봤는데 이제부터는 스트림의 양대산맥인 문자 스트림에 대해 알아본다.
- Write : 바이트 스트림의 OutputStream과 같은 역할
- Reader : 바이트 스트림의 InputStream과 같은 역할
- OutputStreamWriter : 문자 기반의 Writer에서 바이트 기반의 OutputStream 채널로의 연결을 지원 문자->OutputstreamWriter->바이트
- InputStreamReader : 바이트 기반의 InputStream을 문자 스트림과 연결 바이트->InputStreamReader->문자
- FileWriter : 텍스트 파일을 플랫폼의 기본 문자 인코딩 방식을 사용하여 출력하는 문자 스트림 인터페이스를 제공 파일에 쓰는것임 --;
- FileReader : 플랫폼의 기본 문자 인코딩 방식을 사용하여 텍스트 파일을 읽기 위한 문자 스트림 인터페이스를 제공한다. 파일에서 읽는것임 --;
2.7. Chapter11 문자 스트림 필터 ¶
- 바이트 스트림에서 기능을 확장하기위한 필터가 있었듯이 문자 스트림에도 필터가 있다.
- FilterWriter : 모든 문자 스트림 필터의 스퍼클래스로 다른 Writer 객체에 연결되어서 모든 호출 연결된 스트림으로 전달한다.
- FilterReader : 모든 Reader 문자 스트림 필터의 수퍼클래스로, 다른 Reader객체와 연결하여 모든 메소드의 호출을 연결된 스트림으로 전돨한다.
- BufferedWriter : 연결된 스트림에 출력 버퍼링 기능을 제공한다. 모든데이터는 버퍼가 가득 찾거나 flush() 메소드가 호출되거나 close() 메소드가 호출될 때까지 내부 버퍼에 저장되었다가 여러 문자를 한꺼번에 출력하는 write()메소드의 호출을 통해 연결된 스트림으로 출력된다.
- BufferdReader : 연결된 스트림에 입력 버퍼링을 제공하는 FilterReader이다. 데이터는 커다란 덩어리로 한꺼번에 연결된 스트림에서 내부 버퍼로 읽혀지므로 작은 크기의 데이터는 내부 버퍼로부터 효율적으로 읽힐 수 있다.
- LineNumberReader :연결된 스트림의 텍스트를 구성하는 각줄의 번호를 카운팅하는 기능을 초보적으로 나마 제공한다. 이클래스는 BufferedReader의 서브클래스이므로, 연결된 스트림으로서의 버퍼링을 자동으로 제공한다.
- PrintWriter : PrintStream을 대체하는 Writer 클래스로 데이터를 텍스트 형식으로 출력하는 메소드를 제공한다.
- PushbackReader : PushbackInputStream과 마찬가지로 ,푸시백 버퍼를 제공하여 이미 읽은 문자의 복구기능을 제공해 주는 클래스이다.
2.9. Chapter13 파워업! 객체 스트림 ¶
- 이번장에서 Object를 통신채널로 전송할수있는 객체 스트림에 대해 배우고있다 --;
- ObjectOutputStream,ObjectInputStream에 대해 자세히 배우는데 개념이 좀 맘에 안온다.
- 끝에 예제를 보고 조금 이해가 가긴하는데 다음장부터 본격적인 네트웍으로써 이해를 하겠다 --;
- 객체 스트림의 서브클래스 구현 : 직렬화 될수 없고, 그외 여러가지 방법으로도 직렬화시키기 어려운 클래스의 전송을 제공하기 위해 객체 스트림의 서브클래스를 구형해야함
~cpp interface MyOSContants { final short myOSMagick = (short)0x1359; final short myOSVersion = (short)0x0010; } import java.io.*; import java.net.*; public class MyDatagramPacket implements Serializable { //이클래스는 직렬화를 할수있다. private byte[] data; //직렬화를 할수없는 DatagramPacket을 깜싸서 직렬화를 할수있게한다. private int offset,length,port; private InetAddress address; MyDatagramPacket(DatagramPacket packet) { //DatagramPacket으로부터 정보를 념겨받는다. data = packet.getData(); offset = packet.getOffset(); address = packet.getAddress(); port = packet.getPort(); } DatagramPacket toDatagramPacket(){ //DatagramPacket을 넘겨준다. return new DatagramPacket(data,offset,length,address,port); } } import java.io.*; public class MyFile extends File{//이클래스 자체로 직렬화할수있지만 예제다 --; private String originalPath; //오리지날 패스 public MyFile(File file) { //파일을 받고 super(file.getAbsolutePath()); //절대경로를 넘겨준다/ originalPath = file.getPath(); //오리지날 패스를 받는다. } public String getOriginalPath(){ return originalPath; } } import java.io.*; import java.net.*; public class MyAltDatagramPacket extends MyDatagramPacket { public MyAltDatagramPacket(DatagramPacket packet) { super(packet); } private Object readResolve(){ return toDatagramPacket(); } } import java.io.*; import java.net.*; public class MyObjectOutputStream extends ObjectOutputStream implements MyOSContants{ public MyObjectOutputStream(OutputStream out)throws IOException { super(out); enableReplaceObject(true); //이메소드를 호출해야만 replaceObject를 호출할수있음 보안문제 } protected void writeStreamHeader() throws IOException{ super.writeStreamHeader(); //수퍼클래스의 헤더를 출력한후에 writeShort(myOSMagick); //스트림의 메직넘버인 myOSMagick과 writeShort(myOSVersion); //버전 번호인 myOSVersion을 출력한다. } protected Object replaceObject(Object object) throws IOException{ if(object.getClass() == DatagramPacket.class) return new MyDatagramPacket((DatagramPacket)object); else if(object.getClass().getName().equals("java.io.File")) return new MyFile((File)object); else return object; } } import java.io.*; import java.net.*; public class MyObjectInputStream extends ObjectInputStream implements MyOSContants { public MyObjectInputStream(InputStream in)throws IOException { super(in); enableResolveObject(true); //resolveObject()호출 가능하게한다. } protected void readStreamHeader() throws IOException{ //스트림을 읽는다. super.readStreamHeader(); if(readShort() !=myOSMagick) //고유번호가 틀리면 throw new StreamCorruptedException("Incompatible myOSMagick number"); if(readShort() > myOSVersion) //버전이 높으면 throw new StreamCorruptedException("Incompatible myOSVersion number"); } protected Object resolveObject(Object object) throws IOException{ if(object instanceof MyDatagramPacket) return ((MyDatagramPacket)object).toDatagramPacket(); else return object; } }
- PART2를 마치며 : 그동안 자바책을 보면서 한번도 깊이 접해보지못한 스트림에관해 배웠다. 재밌었다 ^^;;