Presentation is loading. Please wait.

Presentation is loading. Please wait.

6장 java.applet.Applet의 네트워크 메쏘드들

Similar presentations


Presentation on theme: "6장 java.applet.Applet의 네트워크 메쏘드들"— Presentation transcript:

1 6장 java.applet.Applet의 네트워크 메쏘드들
발표자 : 최용준, 박학수 SE Lab

2 목차 Applet Data download하기 위한 Methods ImageObserver Interface
MediaTracker Class AppletContext Interface 유용한 프로그램들(ImageSizer) 먼저 6장을 발표하기 전에 6장보다 선행되어야 할 자바의 기초적인 부분들, applet, html 그리고 thread에 대한 사전 공부를 한 후에 본 6장 java.applet.Applet의 네트워크 메쏘드들에 대한 부분들을 다뤄보도록 하겠습니다. 먼저 applet의 기초를 살펴보고, applet와 관련된 html에서 사용되는 tag들을 간략히 살펴보고, 유용한 프로그램들에서 종종 보여지는 thread를 마지막으로 살펴보고, 본 6장에서 다뤄지는 data를 다운로드하기 위한 메소드들, ImageObserver Interface에 대해서 살펴보고, MediaTracker Class를 살펴보고, AppletContext Interface를 살펴본 후 마지막으로 유용한 프로그램들에 대해 살펴보겠습니다. SE Lab

3 Applet의 기초(1/5) 특징 Main() 메소드를 갖지 않음
WWW 검색기, Appletviewer의 데이터 창에서만 수행되는 제한된 프로그램 생성되고 실행이 종료될 때까지 일정한 동작을 반복하는 Applet life cycle 실행 명령에 의해 실행되지 않고, WWW의 HTML 코드 내에서 호출되어 실행되는 형태 Applet class는 항상 public으로 선언 애플릿이란 보안이 설정된 브라우저 안에서 실행되며, 웹 문서에 내장되는(embedded) 프로그램을 말한다. SE Lab

4 Applet의 기초(2/5) Applet과 Application의 비교 Applet Application
WWW 브라우져 내에서만 실행, HTML Tag를 사용해서 내장 Main method가 존재하지 않음 Main에 해당하는 부분은 브라우저 내에 포함되어 있다가 이벤트가 발생했을 때마다 실행 Application 자바 인터프리터 사용, 독립적 실행 SE Lab

5 Applet의 기초(3/5) Applet Class Java.lang.Object Java.awt.Component 추상클래스
Java.awt.Container 추상클래스 추상클래스 : 하위클래스에서 사용되는 구체적인 기능들을 추상적으로 정의해놓은 클래스 Component 클래스는 gui 구축에 필요한 하위클래스를 가지고 있고, 약 100여개의 메소드를 정의하고 있다. 예로, getFont(), paint() Java.awt.Panel Java.applet.Applet Panel Class로부터 상속 SE Lab

6 Applet의 기초(4/5) Applet Class’s Method 메소드 설 명 Void init() 애플릿을 초기화
설 명 Void init() 애플릿을 초기화 Void start() 애플릿을 시작 Void stop() 애플릿을 중단 Vlid destroy() 애플릿을 끝낸다. URL getCodeBase() 애플릿 코드가 있는 URL 객체 반환 URL getDocumentBase() HTML 문서가 있는 URL 객체 반환 Image getImage(URL url) url(파일이름 포함)이 지정하는 곳에서 이미지를 가져와 Image 객체로 반환 Image getParameter(String pName) 애플릿이 호출시 사용한 매개변수 중 pName 매개변수의 값을 반환 SE Lab

7 Applet의 기초(5/5) Applet’s Lifecycle Init() start() stop() destroy()
처음 방문시 애플릿 페이지로 복귀할 때 애플릿을 종료 Init() start() stop() destroy() 페이지를 떠날 때 paint() Paint() 메소드는 애플릿에 그래픽을 출력하기 위한 메소드이다. Start() 또는 init()에 의해 자동으로 호출되어 수행된다. SE Lab

8 Applet에서의 HTML(1/3) Applet Tag CODEBASE : Applet 파일이 로드될 디렉토리를 지정하는 속성
ALT : 검색기가 Applet을 실행할 수 없을 때 나타낼 메시지 를 지정 NAME : Applet 객체의 이름을 지정 WIDTH와 HEIGHT : 검색기의 데이터 창에 나타낼 Applet의 크기를 지정 PARAM NAME과 VALUE : Applet에 넘겨줄 데이터를 지정 SE Lab

9 Applet에서의 HTML(2/3) HTML 예제 <html> <head>
<title>ImageMapApplet</title> </head> <body> <h1>ImageMapApplet</h1> <applet code=ImageMapApplet width=300 height=80> <param name=filename value=mapfile.gif> </applet> </body> </html> SE Lab

10 Applet에서의 HTML(3/3) 경로지정방식 절대 경로 형식 상대 경로 형식
<applet codebase=“c:\applet\class” code=“test.class” width=200 height=80> </applet> 상대 경로 형식 <applet codebase=“class” code=“test.class” width=200 height=80> SE Lab

11 Applet에서의 Thread(1/4) Process와 Thread Process Thread 실행중인 하나의 프로그램
하나의 프로세스에 하나 이상의 스레드 생성 (다중 스레드) Thread를 사용하는 이유는 실시간으로 여러 가지 일을 동시에 하는 프로그램을 작성한다고 생각해보자. 예를 들어, 통신을 통하여 데이터를 받는 동시에, 받은 데이터를 가공하여 다른 곳으로 보내는 프로그램을 작성한다. 가장 먼저 생각되는 프로그램 형태는 하나의 while 루프 안에 입력 데이터를 처리하는 부분, 데이터를 송신하는 부분을 차례대로 구현하는 것이다. 각 부분은 순차적으로 수행된다. 그러나 만약 데이터를 처리하는 부분에서 시간을 많이 소모하였을 경우에는 어떻게 되는가? 입력 데이터를 받는 버퍼가 오버플로우가 되어 입력데이터를 잃어버릴 수도 있을 것이다. 출력에 있어서도 마찬가지이다. Dos 시대에 한번에 하나의 작업밖에 못했던 시절의 답답함을 기억해보면 이런 경우에는 최선의 방법은 프로세스 스케줄러를 설계하고 각 부분을 프로세스로 만들어 서로 독립적인 프로세스로 동시에 수행시키는 것이다… 그러나 프로세스가 동시에 수행되면 동기화라고 하는 까다로운 문제가 생기므로 이에 대한 해법으로 스레드를 사용하는 것이다. 동기화에 대한 해결방법으로는 임계영역을 만듦으로써 해결할 수 있다. 비행기의 활주로를 생각해보면 된다. 동기화 되어야 할 부분에synchronized 키워드를 사용하면 된다. 이에 대한 자세한 설명은 생략하기로 한다. SE Lab

12 Applet에서의 Thread(2/4) Thread의 lifecycle 완료 ` 생성 대기
[ 생성상태 ] Thread 클래스를 이용하여 새로운 스레드를 생성한 상태이다. 그러나 생성만 되었을 뿐 스레드가 아직은 시작된 것은 아니다. start() 는 생성된 스레드를 시작하게 한다. Start()는 run()을 호출하게 되어 있다. 따라서 생성된 스레드에 자원을 할당하여 스레드를 실행가능상태로 만든다. Stop()은 생성된 스레드를 멈추게 한다. [ 실행가능상태 - 실행상태 ] 생성상태에서 start() 메소드를 호출하면 run()이 호출되어 스레드가 실행가능상태로 오게 된다. 스레드가 스케쥴링 큐에 넣어지고 스케줄러에 의해 우선순위에 따라 실행된다. [ 대기 ] 실행가능상태에서 대기상태로 스레드나 다른 스레드가 suspend() 를 호출하는 경우 -- 1 스레드가 wait() 를 호출하는 경우 -- 2 스레드가 sleep()을 호출하는 경우 -- 3 스레드가 입출력 작업을 하기 위해 대기하는 경우 -- 4 대기상태에서 실행가능상태로 resume()이 호출되어야 한다 Notify()나 notifyAll()이 호출되어야 한다 지정된 sleep 시간이 경과되어야 한다 입출력 작업이 완료되어야 한다 [ 완료 ] 정상적인 종료와 강제적인 종료 두가지가 있다. Run() 메소드가 동작을 끝내고 종료하는 경우 Stop() 메소드를 사용하여 정지시켜 종료시키는 것이다. 강제적인 종료를 함으로써 얻어지는 이익은 어떤 특정한 조건이 발생하면 스레드를 언제든지 종료시킬 수 있다는 것이다. 실행 상태 ` Sleep(), wait(), suspend(), 입출력등 생성 Start() 대기 실행가능 상태 notify(), notifyAll() resume(), 입출력 완료 등 SE Lab

13 Applet에서의 Thread(3/4) Thread 생성(1/2) Thread Class 이용 클래스 생성하는 예
class ThreadA extends Thread { public void run() { } 객체 생성하는 예 ThreadA ta = new ThreadA(); ta.start(); 이 방법은 thread(java.lang.thread) 클래스로부터 직접 상속받아 스레드 특징을 가지는 클래스를 생성하여 스레드를 사용하는 방법이다. Thread 클래스는 스레드의 실행부분을 지정하는 run() 메소드를 제공한다. Thread 클래스로부터 상속되어 생성된 클래스에서는 thread 클래스에 정의된 run() 메소드를 오버라이딩하여 스레드의 동작을 기술하여야 한다 . SE Lab

14 Applet에서의 Thread(4/4) Thread 생성(2/2) Runnable Interface 이용 클래스 생성하는 예
class RunnableB extends Applet implements Runnable { public void run() { } 객체 생성하는 예 RunnableB rb = new RunnableB(); new Thread(rb).start(); 스레드의 특성을 가져야 하는 클래스가 이미 다른 클래스로부터 상속을 받고 있다면 runnable interface를 이용해야 한다. Runnable interface에는 다음과 같이 run() 메소드 하나만 선언되어 있으며 jdk에 의해 제공되고 있는 라이브러리 인터페이스이다. SE Lab

15 Data Download 관련된 정보 가져오기 이미지 다운로드 사운드 다운로드 getDocumentBase()
getCodeBase() 이미지 다운로드 getImage() 사운드 다운로드 play() getAudioClip() getDocumentBase()는 html이 들어있는 url 객체를 반환 getCodeBase()는 applet 파일이 들어있는 디렉톡리의 url 객체를 반환 getImage()는 url에 있는 그림파일 반환 Play()는 사운드 파일을 연주 getAudioClip()는 audioclip 객체 생성하여 play()와 loop()를 반복하게 해준다. SE Lab

16 관련된 정보 가져오기 Public URL getDocumentBase() Public URL getCodeBase()
Public void paint(Graphic g) { g.drawString(getDocumentBase().toString(), 25, 50); } Public URL getCodeBase() 애플릿 디렉토리의 URL을 반환 실행 예(AppletBases) SE Lab

17 이미지 다운로드하기(1/2) 실행 예(ImageView) Public Image getImage(URL u)
지정된 URL에 있는 이미지 데이터를 가져와 Image 객체 안에 저장 URL u = new URL(“ Image myLogo = getImage(u) 실행 예(ImageView) SE Lab

18 이미지 다운로드하기(2/2) Public Image getImage(URL u, String filename)
Image myLogo = getImage(new URL(“ “logo.gif”); Image myImage = getImage(getCodeBase(), “logo.gif”); Image myImage = getImage(getDocumentsBase(), “logo.gif”); SE Lab

19 사운드 다운로드하기(1/4) Public void play(URL u)
try { play(new URL(“ } catch (MalformedURLException e) { System.err.println(e); SE Lab

20 사운드 다운로드하기(2/4) Public void play(URL u, String filename)
try { play(new URL(“ “gong.au); } catch(MalformedURLException e) { System.err.println(e); } Play(new URL(“ “gong.au”); Play(getCodeBase(), “gong.au”); Play(getDocumentBase(), getParameter(“soundfile”)); 만약 사운드 파일이 HTML 문서가 들어있는 디렉토리내의 서브디렉토리인 sounds 디렉토리에 있다면, play(getDocumentBase(), “sounds/gong.au”); SE Lab

21 사운드 다운로드하기(3/4) Public AudioClip getAudioClip(URL u)
AudioClip theGong; URL u; try { u=new URL( theGong = getAudioClip(u); } catch(MalformedURLException e) { System.err.println(e); } AudioClip 인터페이스는 사운드를 나타낸다. 웹 사이트에서 사운드를 다운로드한 후 AudioClip 객체를 갖게 되면 원하는 때에 AudioClip 객체를 이용하여 play()와 loop()를 반복할 수 있다. SE Lab

22 사운드 다운로드하기(4/4) Public AudioClip getAudioClip (URL u, String filename)
AudioClip ac = getAudioClip(new URL(“ “gong.au”); 실행 예(RelativeGong) 스레드에 대한 정의를 다시 한번 짚어준다. Init() : 초기화 해준후 start() 메소드를 호출한다. start() : resume() 메소드는 일시 정지된 스레드를 다시 시작한다. stop() : suspend() 메소드는 스레드를 일시 정지시킨다. Resume() 메소드에 의해 다시 시작된다. run() : start() 메쏘드가 호출한다. Start() 메소드가 없을 시에는 init() 메소드 담으로 호출된다. 스레드가 실행할 부분을 기술하는 메소드. 하위 클래스에서 오버라이딩 되어야 한다. currentThread() : 현재 수행되고 있는 스레드 객체를 반환 setPriority() : 객체의 우선순위를 설정 MIN_PRIORITY : 스레드가 가질 수 있는 최소한의 우선순위를 준다. MAX_PRIORITY : 스레드가 가질 수 있는 최대한의 우선순위를 준다. SE Lab

23 ImageObserver Interface(1/2)
이미지 적재의 진행과정을 모니터한다. 준비가 되면 그리기를 실행한다. imageUpdate() 이미지의 상태 체크, 응답 public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height); 실행 예(ShowImage) 파일을 네트워크상에서 다운로드 받는다면 작은 용량의 이미지 파일이 적재되더라도 수분이 걸리는 경우가 드물지 않게 있다. 그러나 자바의 경우 이미지 적재는 주프로그램이 담당하는 것이 아니라, 스레드 객체를 생성시켜서 스레드 객체가 담당하기 때문에 이미지 다운로드와 관련없는 다른 작업을 수행할 수 있다. 이미지 다운로드가 시간이 많이 걸린다면 사용자들은 조바심을 내기 때문에 ImageObserver Interface의 기능은 현재 이미지가 얼마만큼 다운로드 되었는지, 얼마나 기다려야 하는지를 알려주는 기능을 한다. [ Java.awt.image.ImageObserver 인터페이스 ] ImageObserver Interface의 기능 Image 객체들이 이미지 적재의 진행과정을 모니터한다. 사용준비가 되면 Image 그리기 등과 같은 행동을 취할 수 있도록 해준다. 여러분은 MemoryImageSource나 또는 다른 종류의 ImageProducer 를 사용하여 생성되는 이미지의 진행과정을 추적하기 위해 ImageObserver 객체를 사용할 수 있다. SE Lab

24 ImageObserver Interface(2/2)
flag Flag가 설정되었을 때의 의미 .WIDTH Width 인자를 통해 이미지의 넓이를 알 수 있다. .HEIGHT Height 인자를 통해 이미지의 높이를 알 수 있다. .PROPERTIES 이미지 속성들에 대한 정보가 이용 가능하다. .SOMEBITS 이미지를 그리기 위해 필요한 일부분이 전송되었다. .FRAMEBITS 이미지의 여러 개 프레임중 하나가 이용 가능하다. .ALLBITS 이미지 완성 .ERROR 이미지 적재중 에러 발생 .ABORT 이미지가 완성되기 전에 적재는 포기되었다. SE Lab

25 MediaTracker Class(1/10)
ImageObserver와 MediaTracker 하나의 이미지 파일을 모니터하는데는 ImgaeObserver 인터페이스가 유용 이미지가 여러장이거나, 오디오파일같은 매체 유형인 경우 MediaTracker가 유용 MediaTracker Class 사용방법 MediaTracker 인스턴스 생성 Track에 이미지를 추가하기 위해 addImage() 사용 Image에 수치 id를 부여, 그룹일 경우 그룹에 하나의 id 부여 SE Lab

26 MediaTracker Class(2/10)
실행 예(trackImage) 생성자 Public MediaTracker(Component comp) 예) MediaTracker theTracker = new MediaTracker(this); 생성자 인자인 component는 추적하고자 하는 이미지를 화면에 보여준다. 거의 대부분의 이미지를 그려낼 컴포넌트의 정의 내에서 이 생성자가 호출된다. 따라서 MediaTracker()의 인자는 보통의 경우 this이다. SE Lab

27 MediaTracker Class(3/10)
Public void addImage(Image img, int id) Image thePicture = getImage(getDocumentBase(), “logo.gif”); MediaTracker theTracker = new MediaTracker(this); theTracker.addImage(thePicture, 1) Public synchronized void addImage(Image img, int id, int w, int h) theTracker.addImage(thePicture, 1, 30, 30) addImage()는 MediaTracker에 의해 추적되고 있는 이미지의 목록에 새로운 Image img를 추하가고, 추가된 이미지에 ID 번호 id를 부여한다. 이미지는 자신의 원래 크기대로 그려진다. 다음의 부붙코드는 웹 문서와 같은 디렉토리에 들어있는 Logo.gif라는 이미지를 추적하기 위한 것이고, 여기서 이미지는 id 번호 1번이 부여되었다. Synchronized 는 이미지 넓이 w, 높이 h의 크기대로 화면에 그려진다. 넓이 30픽셀, 높이 30픽셀로 조절된다. SE Lab

28 MediaTracker Class(4/10)
매체의 상태 체크하기(1/2) Public boolean checkID(int id) Public void paint(Graphic g) { if(theTracker.checkID(1)) { g.drawImage(thePicture.0,0,this); } else { g.drawString(“Loading Picture, Please hang on”, 25,50); } } Public synchronized boolean checkID(int id, boolean load) boolean load : true면 아직 적재되지 않은 id의 모든 이미지들이 적재되기 시작할 것이다. checkID()는 MediaTracker에 의해 추적되고 있는 ID 번호를 가진 모든 이미지들이 적재를 마쳤는지를 체크한다. 마쳤으면 true 그렇지 않으면 false를 반환한다. checkAll()은 객체들에 의해 추적되고 있는 모든 이미지들이 적재를 마쳤는지를 체크하지만 ID 번호는 고려되지 않는다. SE Lab

29 MediaTracker Class(5/10)
매체의 상태 체크하기(2/2) Public boolean checkAll() 객체들에 의해 추적되고 있는 이미지들이 적재를 마쳤는지를 체크 Id번호는 고려되지 않는다. Public synchronized boolean checkAll( boolean load) 적재를 마쳤으면 true, 그렇지 않으면 false를 반환 Boolean load 인자가 true면 아직 적재되지 않은 이미지들이 적재를 시작한다. 위의 예제는 책에 없는 이유도 있고, 프로그램 작성시 checkID를 checkAll()로 바꾸어 실습해보면 되기에 생략되었습니다. SE Lab

30 MediaTracker Class(6/10)
매체가 적재되기를 기다리기 Public void waitForID(int id) throws InterruptedException Public synchronized boolean waitForID(int id, long ms) throws InterruptedException Public synchronized boolean waitForAll() throws InterruptedException Public synchronized boolean waitForAll(long ms) throws InterruptedException MediaTracker에 의해 추적되고 있는 이미지들의 적재를 시작하고 적재가 완료될 때까지 기다린다. 이미지 적재가 완료되기 전까지, 소스 코드는 더 이상 진행되지 않는다. 이미지가 다운로드되는 동안, 프로그램이 다른 작업을 수행하도록 하려면, 위 메쏘드를 독립된 쓰레드 안에서 호출해야 한다. SE Lab

31 MediaTracker Class(7/10)
에러 체크하기(1/2) Public synchronized boolean isErrorAny() If (theTracker.isErrorAny()) { System.err.println(“There was an error while loading media”); } Public synchronized Object[] getErrorsAny() System.err.println(“The follow media encountered errors while loading”); Object[] failedMedia = theTracker.getErrorsAny(); For (int I = 0 ; I<10 ; I++) { System.err.println(failedMedia[]); } } Public synchronized boolean isErrorAny() 이미지 적재시 에러 발생 체크 Public synchronized Object[] getErrorsAny() 에러가 난 객체들을 포함하여 배열을 반환한다. 에러 발생하지 않으면 null 을 반환한다. SE Lab

32 MediaTracker Class(8/10)
에러 체크하기(2/2) Public synchronized boolean isErrorID(int id) If (theTracker.isErrorID(2)) { System.err.println(“There was an error while loading media with ID” + 2); } Public synchronized Object[] getErrorsID(int id) If (theTracker.isErrorsID(2)) { System.err.println(“The follow media encountered errors while loading”); Object[] failedMedia = theTracker.getErrorsID(2); For (int I = 0 ; I<10 ; I++) { System.err.println(failedMedia[i]); } } Public synchronized boolean isErrorID(int id) 이 메소드는 만약 지정된 id 번호를 가진 매체 중이 어느 하나라도 적재 중에 에러를 만났다면 true를 반환하고, 그렇지 않으면 false를 반환한다. 에러가 있으면 getErrorsID()를 사용해서 에러를 반환한 객체를 알아낼 수 있다. 여기서 하나의 id가 여러 개의 이미지를 가리킬 수 있는데 이들 중 최소한 어느 하나가 에러를 만났음을 뜻한다. SE Lab

33 MediaTracker Class(9/10)
매체의 상태 체크하기(1) 매체 상태 상수 상 수 의 미 MediaTracker.LOADING 1 그룹안에 최소한 하나 이상의 이미지 다운로드중이다. MediaTracker.ABORTED 2 그룹안에 최소한 하나 이상의 이미지 적재 프로세스가 포기되었다. MediaTracker.ERRORED 4 그룹안에 있는 최소한 하나 이상의 이미지가 적재 중 에러 발생되었다. MediaTracker.COMPLETE 8 그룹안에 있는 최소한 하나 이상의 이미지가 성공적으로 다운로드되었다. 이 메쏘드들은 그룹에 속해 있는 개별 이미지들에 대한 상태정보를 알아낼 수 없다. 이것은 이미지 그룹의 크기를 작게 하기 위해서이다. MediaTracker 클래스는 상태를 보고하기 위해 의심이 가는 이미지 그룹에 적재중인지, 포기되었는지, 에러가 발생했는지, 적재가 완료되었는지를 알려주는 플래그 상수들을 포함하고 있다. 위 표의 상수들은 다음의 상태 정보 메쏘드들이 반환하는 값들을 테스트하여 특정한 상태, 또는 상태들의 조합이 true인지를 알아내기 위해 사용된다. 이 상수들은 2의 승수 값들이므로, 각각은 정확히 한 비트 세트(bitset)를 가지며, 비트 연산자와 조합되어 상태들의 조합을 테스트할 수 있다. SE Lab

34 MediaTracker Class(10/10)
Public int statusAll(boolean load) MediaTracker 객체에 의해 추적되는 모든 매체의 상태를 반환 If ((m.statusAll(false) & ImageObserver.COMPLETED) == ImageObserver.COMPLETED) {…} Public int statusAll(int id, boolean load) 추적되는 id 번호를 가진 매체의 상태를 반환 If ((m.statusAll(2, false) & ImageObserver.COMPLETED) == ImageObserver.COMPLETED) {…} 1. 인자가 true이면, 아직 적재를 시작하지 않은 매체는 시작한다. 그러나, 만일 false이면 아무런 작업도 하지 않을 것이다 SE Lab

35 AppletContext 인터페이스의 네트워크 메쏘드들
AppletContext Interface 애플릿으로 하여금 자신이 실행되고 있는 환경을 조작할 수 있도록 해주는 인터페이스 Public void showDocument(URL u) Public void showDocument(URL u, String name) 실행 예(Redirector2) SE Lab

36 유용한 프로그램들 Animator Animator라는 간단한 에니메이션 에플릿이나, 이것은 애플릿의 <param> 태그에서 파일 이름들의 목록을 읽는다.(cell0, cell1, cell2, ..) init()은 존재하지 않는 파일 이름을 발견할 때까지 파라미터를 읽는다. 파일 이름과 문서베이스로 URL을 만들고, getImage()로 이미지를 가져온다. 이미지 객체가 몇 개인지 모르므로, vector에 저장 다운로드된 이미지들은 MediaTracker theTracker에 추가 TheTracker의 checkAll() 메소드는 이미지 적재를 시작하고, 이미지를 연속적으로 보여주기 위해 새로운 쓰레드가 만들어진다. 이미지를 그리기 전에 run() 메소드는 준비되었는지 확인하기 위해 theTracker.waitForID()를 호출한다. SE Lab


Download ppt "6장 java.applet.Applet의 네트워크 메쏘드들"

Similar presentations


Ads by Google