Transcript Document

실습 1 : 분산 시스템 이해 (1)

Sun RPC 익히기

media.incheon.ac.kr과 isis.incheon.ac.kr에 있는 여러분 계정에
서 DATE_PROG 프로그램과 SQUARE_PROG 프로그램을 다운로
드 받아 클라이언트/서버 프로그램을 실행해 보세요.



소스 코드: ftp multi (211.119.245.61) ID:anonymous,
Password: 아무거나로 ftp 접속하면 pub/rpc
(/usr/FTP/pub/rpc) 디렉토리에
http://marvel.incheon.ac.kr의 InformationUnix RPC 참
조
또 C언어 시스템 호출 localtime()를 참조하여 서버 프로그램에 아
래와 같은 형식으로 시간만을 돌려주는 루틴을 추가하고 클라이언
트에서 그 서비스를 받아 보세요.
time on host = 1:23:34

실습방법

media.inchon.ac.kr의 /home1/mysung/2001mmreport 디렉토리
에 자기 학번 디렉토리를 만들고 소스 프로그램과 실행 파일을 옮
겨 놓으세요.
1.1
실습 1 : 분산 시스템 이해 (2)

CORBA 익히기

multi.incheon.ac.kr에서 Account 응용 프로그램을 실행해 보세요.




http://marvel.inchon.ac.kr의 InformationCORBA 참조
소스 코드: ftp multi (211.119.245.61) ID: anonymous,
Password: 아무거나로 ftp 접속하면 pub/account
(/usr/FTP/pub/account)
또한 Windows 환경에서의 CORBA 프로그래밍 연습을 위하여,
Windows에서 VisiBroker for Java 또는 C++을 다운 받아 설치하고,
위 예제 서버 프로그램에 잔고에 대한 일년 이자를 계산하는 메소드
를 추가하고 클라이언트 프로그램에서 방금 조사된 잔고에 대한 이
자를 서버에 요청하여 알아낸 다음 이를 출력하도록 Account 프로
그램을 수정하여 제출하세요. 단, 구현 언어는 Java와 C++ 중 어느
것도 좋습니다.
실습방법

media.inchon.ac.kr의 /home1/mysung/2001mmreport 디렉토리
에 자기 학번 디렉토리를 만들고 소스 프로그램과 실행 파일을 옮겨
놓으세요.
1.2
실습 1 : 분산 시스템 이해 (3)

RMI 익히기

media.incheon.ac.kr에서 분산환경에서 동작하는 messagepassing을 이용한 bounded-buffer 해법 프로그램을 실행해 보세요.





소스 코드: ftp multi (211.119.245.61) ID:anonymous,
Password: 아무거나로 ftp 접속하면 pub/rpc (/usr/FTP/pub/rmi)
디렉토리에
http://marvel.incheon.ac.kr의 InformationUnix RMI 참조
또 이 예제가 웹 상에서 수행될 수 있도록 수정해 보세요. 즉 클라이
언트 프로그램에서 이 예제의 Producer와 Consumer의 동작을 모니
터링하는 Java applet을 작성해 보는 것입니다.
BONUS: Java synchronization을 이용한 bounded-buffer 해법(운영
체제 교재 Applied Operating System Concepts 7장 참조)이 분산 환
경에서도 동작할 수 있도록 RMI를 이용하여 수정해 보세요.
실습방법

media.inchon.ac.kr의 /home1/mysung/2001mmreport 디렉토리에
자기 학번 디렉토리를 만들고 소스 프로그램과 실행 파일을 옮겨 놓
으세요.
1.3
Sun RPC 예제 1: DATE_PROG

구성




rpcgen: remote procedure interface(date.x)를 컴파일하여 server stub와
client stub를 생성
XDR(eXternal Data Representation): 다른 시스템 간에 이식 가능한 형태
로 데이터를 코드화하는 표준 방법
run-time library: 모든 세세한 것들을 다룸; –lnsl(Network Service Library)
처리 방법
% rpcgen date.x
% gcc -o date_svc date_proc.c date_svc.c –lnsl
% gcc -o rdate rdate.c date_clnt.c –lnsl

소스 코드

RPC 명세 파일 date.x

서버 프로그램 date_proc.c

클라이언트 프로그램 rdate.c
ftp 211.119.245.61 ID: anonymous, Password: 아무거나로 ftp 접
속하여 pub/rpc 디렉토리에 있음
1.4
Sun RPC 예제 1: DATE_PROG

실행 방법

서버 호스트에서
$ date_svc &

클라이언트 호스트에서
$ ./rdate 호스트이름(도메인이름 또는 IP 주소)
(실행 파일이 rdate인 경우 /bin 디렉토리 다른 프로그램의 실
행파일인 rdate가 이미 존재할 수 있으므로 rdate 명령 앞에
현재 디렉토리 ./ 붙여서 ./rdate로 실행시킴)
time on host = 984459987 … 00:00:00 GMT(Greenwitch
Mean Time)
January 1, 1970부터의 초의 수
time on host = Tue Mar 13 14:06:27 2001
1.5
Sun RPC 예제 1: DATE_PROG
1.6
Sun RPC 예제 1: DATE_PROG

RPC 명세 파일 : date.x
program DATE_PROG {
version DATE_VERS {
long
BIN_DATE(void) = 1 ; /* procedure no. = 1 */
string STR_DATE(long) = 2 ; /* procedure no. = 2 */
}=1;
/* version no. = 1 */
} = 0x31234567 ;
/* program no. = ox31234567 */

프로그램 번호

0x00000000 ~ 0x1fffffff
Sun에 의해 정의된

0x10000000 ~ 0x3fffffff
사용자에 의해 정의된

0x40000000 ~ 0x5fffffff
일시적인 (transient)

0x60000000 ~ 0xffffffff
예약된 (reserved)
1.7
Sun RPC 예제 1: DATE_PROG

서버 프로그램 : date_proc.c
/* date_proc.c */
#include
<rpc/rpc.h>
#include
"date.h"
long *
bin_date_1()
{
static long
timeval ;
long
time() ;
timeval = time((long *) 0) ;
return(&timeval) ;
}
char **
str_date_1(bintime)
long
*bintime ;
{
static char
*ptr ;
char
*ctime() ;
ptr = ctime(bintime) ;
return(&ptr) ;
}
1.8
Sun RPC 예제 1: DATE_PROG

클라이언트 프로그램 : rdate.c
#include <stdio.h>
#include <rpc/rpc.h>
#include "date.h"
/* generated by rpcgen */
main(argc, argv)
int
argc;
char *argv[];
{
CLIENT *cl;
/* RPC handle */
char *server;
long *lresult;
/* return value from bin_date_1() */
char **sresult;
/* return value from str_date_1() */
if (argc != 2)
fprintf(stderr, "usage: %s hostname\n", argv[0]);
server = argv[1];
if ((cl = clnt_create(server,DATE_PROG,DATE_VERS,"udp"))
== NULL)
clnt_pcreateerror(server);
if ((lresult = bin_date_1(NULL, cl)) == NULL)
clnt_perror(cl, server);
printf("time on host %s = %ld\n", server, *lresult);
if ((sresult = str_date_1(lresult, cl)) == NULL)
clnt_perror(cl, server);
printf("time on host %s = %s", server, *sresult);
clnt_destroy(cl);
}
1.9
Sun RPC 예제 2: SQUARE_PROG

RPC 명세 파일 : square.x
struct square_in {
/* input argument */
long arg1;
};
struct square_out {
/* output result */
long res1;
};
program SQUARE_PROG {
version SQUARE_PROG {
square_out SQUAREPROC (square_in) = 1; /* procedure no. =1 */
} = 1;
/* version number */
} = 0x31230000
/* program number */


소스 코드 : square.x server.c client.c
처리 방법
% rpcgen square.x
% gcc -o server server.c square_svc.c square_xdr.c -lnsl
% gcc -o client client.c square_clnt.c square_xdr.c -lnsl

RPC 명세 파일에 구조체를 포함하기 때문에 square_xdr.c 파일이 생성
되므로 컴파일시 square.xdr.c 파일을 반드시 포함해야 함
1.10
Sun RPC 예제 2: SQUARE_PROG

그림
1.11
Sun RPC 예제 2: SQUARE_PROG

그림
1.12
Sun RPC 예제 2: SQUARE_PROG

서버 프로그램 : server.c
#include
“square.h”
square_out *
squareproc_1 (square_in *inp, struct svc_req *rqstp)
{
static square_out
out ;
out.res1 = inp -> arg1 * inp -> arg1 ;
return (&out);
}
1.13
Sun RPC 예제 2: SQUARE_PROG

클라이언트 프로그램 : client.c
#include “square.h”
int main(int argc, char **argv) {
CLIENT
*cl ;
square_in
in ;
square_out
*outp ;
if ( argc != 3 )
clnt_perror(cl, “usage : client <hostname> <interger_value>”);
cl = cInt_create(argv[1], SQUARE_PROG, SQUARE_VERS, “tcp”);
in.arg1 = (long)atol(argv[2]);
if ( ( outp = squareproc_1(&in, cl) ) == NULL)
clnt_perror( cl, argv[1] ) ;
printf(“result : %ld\n”, outp -> res1);
exit(0)
}
1.14
CORBA 프로그램 예제 1


구성

IDL(interface Definition Language) 파일 account.idl

서버 프로그램 account_srvr.C

클라이언트 프로그램 account_clnt.C
원격 서버에 잔고를 요청하여 알려주는 Account 응용의 IDL 명세
// Account.idl
interface Account {
float balance();
};
1.15
CORBA 프로그램 예제 1
Server Program
Server
account_srvr.C
cc
account_server
Server Skeleton
account_s.hh
account.idl
idl2cpp
account_s.cc
Visibroker
account_c.hh
Library
account_c.cc
Client
account_clnt.C
Client Program
Client Stub
cc
account_client
1.16
CORBA 프로그램 예제 1

프로그램의 Compile

Makefile의 실행
prompt> make
(make는 실행파일로 Makefile이 있을경우에 자동으로 make –f
Makefile을 실행시켜 준다.)

Makefile의 내용
 include ./stdmk : stdmk를 불러낸다. stdmk는 컴파일러의 옵
션(멀티 스레트 프로그램, 소켓, 디버그등)과 라이브러리 선언,
그리고 여러 C파일의 확장자별로 다른 컴파일 환경에 대해서
설정해 놓았다.
 idl2cpp를 이용해 생성되는 파일
: account_c.hh, account_c.cc, account_s.hh account_s.cc
 account_server의 생성
: account_srvr.C와 account_c.cc(account_c.hh포함)과
account_s.cc(account_s.hh포함)을 컴파일하여 생성.
 account_client의 생성
: account_clnt.C와 account_c.cc(account_c.hh포함)를 컴파
일하여 생성.
1.17
CORBA 프로그램 예제 1

프로그램의 실행
3. Client실행
2. Server실행
• stub 모듈
• Skeleton 모듈
1. Agent 실행
Object Request Broker
1. make를 실행하여 컴파일한다.
2. Visibroker에서 osagent를 실행시킨다.
prompt> cd /opt/vbroker/bin/
prompt> osagent
3. Server 객체를 실행시킨다.
prompt> account_server
4. Client 객체를 실행시킨다.
prompt> account_client
1.18
CORBA 프로그램 예제 1

Server Program(1/2)
// account_srvr.C
#include "account_s.hh"
#include <math.h>
class AccountImpl
{
private:
CORBA::Float _balance;
public:
AccountImpl(const char *object_name=NULL)
{
// Set a random balance between 0 and 10000
_balance = abs(rand()) % 100000 / 100.0;
}
CORBA::Float balance()
{
return _balance;
}
};
1.19
CORBA 프로그램 예제 1

Server Program(2/2)
int main(int argc, char* const* argv) {
try {
// Initialize the ORB(Object Request Broker) and BOA (Basic Object Adapter)
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_ptr boa = orb->BOA_init(argc, argv);
// Create a new account object.
AccountImpl account(“Jack B. Quick”);
// Export the newly created object.
boa->obj_is_ready(&account);
cout << "Account object is ready." << endl;
// Wait for incoming requests
boa->impl_is_ready();
} catch(const CORBA::Exception& e) {
cerr << e << endl;
return(1); }
return(0); }
1.20
CORBA 프로그램 예제 1

Client Program
#include "account_c.hh"
int main(int argc, char* const* argv) {
try {
// Initialize the ORB.
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// Bind to an account.
Account_var account = Account::_bind();
// use argv[1] as the account name, or a default.
CORBA::String_var name;
if (argc >= 2)
name = (const char *) argv[1];
else
name = (const char *) "Default Name";
// Get the balance of the account.
CORBA::Float acct_balance = account->balance();
// Print out the balance.
cout << "The balance in " << name << "'s account is $";
cout << acct_balance << "." << endl;
} catch(const CORBA::Exception& e) {
cerr << e << endl;
return(1);
}
return(0);
}
1.21
CORBA 프로그램 예제 2


Window용 Visibroker for java, cpp
(http://www.inprise.com/visibroker/)
Visibroker for java의 설치

CORBA Java 프로그램을 개발하기 위해서는 JDK가 설치되어 있어야 한다.
설치후 path를 지정해 준다.

path = c:/jdk1.3/bin;%PATH%
1.
처음에 이름과 회사명과 License Key를 입력한다. 60일동안만 사용하는
Trial버전이므로 License Key는 입력하지 않는다.
2.
설치할 위치를 묻는데 Java와 C++의 사용하는 라이브러리가 틀리므로 같은
디렉토리에 같이 설치하면 안되므로 주의하여 입력한다.
3.
필요한 컴포넌트를 설치한다. Java ORB와 Document, Console의 설치여
부를 결정한다.
4.
OSAGENT_PORT와 VBROKER_ADM을 정해준다. 이 값들은 나중에 변경이
가능하다.
5.
Path변경과 NT Service등록이 있는데, Path 변경만 선택한 후 (Service등록
은 Visibroker Activation Daemon과 Smart Agent가 등록됨) path를 지정해
준다.

path = c:/inprise/vbroker/bin;%PATH%
6.
prompt>idl2java –version으로 테스트
1.22
CORBA 프로그램 예제 2
Server Program
Server
Server.java
vbjc
Server.class
Server Skeleton
bank.idl
Client
Client.java
idl2java
bank 디렉토리
(account.class
…)
AccountImpl.java
AccountManager
Impl.java
Client Program
Client Stub
vbjc
Client.class
1.23
CORBA 프로그램 예제 2

vbmake.bat
@echo off
rem Makefile
if "%1"=="" goto all
if "%1"=="clean" goto clean
goto usage
:all
echo Building the basic/bank_agent example ...
call idl2java Bank.idl
vbjc Client.java
vbjc Server.java
goto end
:clean
if "%OS%"=="Windows_NT" goto nt
deltree /y Bank
del *.class
goto end
:nt
rd /s /q Bank
del /q *.class
goto end
:usage
echo Usage: vbmake [clean]
:end
1.24
CORBA 프로그램 예제 2

프로그램의 실행
3. Client실행
2. Server실행
• stub 모듈
• Skeleton 모듈
1. Agent 실행
Object Request Broker
1. vbmake를 실행하여 컴파일한다.
prompt> vbmake
2. Visibroker에서 osagent를 실행시킨다.
prompt>osagent
3. Server 객체를 실행시킨다.
prompt>cd c:\Inprise\vbroker\examples\basic\bank_agent
prompt>start vbj Server
4. Client 객체를 실행시킨다.
prompt>vbj Client
1.25
CORBA 프로그램 예제 2


OSAgent (smartagent)

동적인 분산 디렉토리 서비스 디몬 프로그램
 (cf) SunRPC에서는 portmapper 또는 rpcbind

간단한 네이밍 서비스 제공하며 클라이언트 객체를 발견하는 메커니즘
제공

객체의 reference를 얻기 위해 객체 이름을 주면 그 이름으로 등록된 객
체의 IOR(Interoperable Object Reference) 정보를 넘겨 줌

OSAgent를 실행시키면 정해진 UDP 포트(14000)로 객체의 요청을 기다
림
 서버 객체를 실행시키면 그 서버 객체의 정보가 OSAgent에게 전달
됨(obj_is_ready 메소드로)
 클라이언트가 실행 될 때도 가장 먼저 OSAsgent에게 원하는 객체를
찾아달라고 요청 (bind 메소드로)
POA(Portable Object adapter)

CORBA 2.0에 정의된 BOA(Basic Object Adapter)가 타 ORB와 의 송수
신이 안 되는 문제점을 보완한 CORBA 3.0에서 정의한 새로운 객체 어댑
터 규격

서버에 있는 객체를 대신해서 서비스에 대한 요청을 받아들이는 일을 함

서버 객체의 목록을 유지하고 서버 객체의 인스턴스를 생성하고 서비스
요청을 그 인스턴스에 전달하고 그 인스턴스에 ID(object reference)를
부여하는 일을 함
1.26
CORBA 프로그램 예제 2
bank.idl

// Bank.idl
module Bank {
interface Account {
float balance();
};
interface AccountManager {
Account open(in string name);
};
};
1.27
CORBA 프로그램 예제 2
AccountImpl.java

public class AccountImpl extends Bank.AccountPOA {
public AccountImpl(float balance) {
_balance = balance;
}
public float balance() {
return _balance;
}
private float _balance;
}
1.28
CORBA 프로그램 예제 2

AccountManagerImpl.java (1/2)
import org.omg.PortableServer.*;
import java.util.*;
public class AccountManagerImpl extends Bank.AccountManagerPOA {
public synchronized Bank.Account open(String name) {
// Lookup the account in the account dictionary.
Bank.Account account = (Bank.Account) _accounts.get(name);
// If there was no account in the dictionary, create one.
if(account == null) {
// Make up the account's balance, between 0 and 1000 dollars.
float balance = Math.abs(_random.nextInt()) % 100000 / 100f;
// Create the account implementation, given the balance.
AccountImpl accountServant = new AccountImpl(balance);
try {
// Activate it on the default POA(Portable Object Adapter) which is root POA for this
servant
account =
Bank.AccountHelper.narrow(_default_POA().servant_to_reference(accountServant));
} catch (Exception e) {
e.printStackTrace();
}
1.29
CORBA 프로그램 예제 2
AccountManagerImpl.java (2/2)

// Print out the new account.
System.out.println("Created " + name + "'s account: " + account);
// Save the account in the account dictionary.
_accounts.put(name, account);
}
// Return the account.
return account;
}
private Dictionary _accounts = new Hashtable();
private Random _random = new Random();
}
1.30
CORBA 프로그램 예제 2

Server.java (1/2)
import org.omg.PortableServer.*;
public class Server {
public static void main(String[] args) {
try {
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
// get a reference to the root POA
POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
// Create policies for our persistent POA
org.omg.CORBA.Policy[] policies = {
rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)
};
// Create myPOA with the right policies
POA myPOA = rootPOA.create_POA( "bank_agent_poa", rootPOA.the_POAManager(),
policies );
// Create the servant
AccountManagerImpl managerServant = new AccountManagerImpl();
// Decide on the ID for the servant
byte[] managerId = "BankManager".getBytes();
// Activate the servant with the ID on myPOA
myPOA.activate_object_with_id(managerId, managerServant);
1.31
CORBA 프로그램 예제 2
Server.java (2/2)

// Activate the POA manager
rootPOA.the_POAManager().activate();
System.out.println(myPOA.servant_to_reference(managerServant) +
" is ready.");
// Wait for incoming requests
orb.run();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
1.32
CORBA 프로그램 예제

Client.java
public class Client {
public static void main(String[] args) {
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
// Get the manager Id
byte[] managerId = "BankManager".getBytes();
// Locate an account manager. Give the full POA name and the servant ID.
Bank.AccountManager manager =
Bank.AccountManagerHelper.bind(orb, "/bank_agent_poa", managerId);
// use args[0] as the account name, or a default.
String name = args.length > 0 ? args[0] : "Jack B. Quick";
// Request the account manager to open a named account.
Bank.Account account = manager.open(name);
// Get the balance of the account.
float balance = account.balance();
// Print out the balance.
System.out.println
("The balance in " + name + "'s account is $" + balance);
}
}
1.33
RMI 프로그램 예제
server
MessageQueueImpl.java
javac
MessageQueueImpl.class
MessageQueueImpl_skel.class
원격 인터페이스
MessageQueue.java
javac
rmic
MessageQueueImpl_stub.class
Factory.java
Producer.java
javac
Factory.class
Consumer.java
1.34
RMI 프로그램 예제


구성

원격 인터페이스: MessageQueue.java

서버 프로그램: MessageQueueImpl.java

클라이언트 프로그램: Factory.java, Producer.java, Consumer.java
실행 순서
1. 모든 소스 파일 컴파일
# javac MessageQueue.java MessageQueueImpl.java Factory.java
Producer.java Consumer.java
2. rmic로 stub와 skeleton class 파일 생성
# rmic MessageQueueImpl
3. 레지스트리 시작 (rmiregistry) … osagent 또는 rpcbind 디몬에 해당
# rmiregistry & (Unix)
또는 C:\> start rmiregistry (Windows)
4. 원격 서버 객체의 인스턴스 생성 (JDK 1.2 이상 버전에서는 인증해 주어야 함)
# java -Djava.security.policy=java.policy MessageQueueImpl (JDK 1.2 이상)
또는 # java MessgeQueueImpl (JDK 1.1)
5. 클라이언트에서 원격 객체 실행 시작
# java -Djava.security.policy=java.policy Factory (JDK .2 이상)
또는 # java Factory (JDK 1.1)
1.35
RMI 프로그램 예제
MessageQueue.java
import java.util.*;
import java.rmi.*;

public interface MessageQueue extends java.rmi.Remote
{
/*
* This implements a non-blocking send
*/
public void send(Object item) throws java.rmi.RemoteException;
/*
* This implements a non-blocking receive
*/
public Object receive() throws java.rmi.RemoteException;
}
1.36
RMI 프로그램 예제
MessageQueueImpl.java (1)
import java.util.*;
import java.rmi.*;

public class MessageQueueImpl extends java.rmi.server.UnicastRemoteObject
implements MessageQueue
{
public MessageQueueImpl() throws RemoteException {
queue = new Vector();
}
// This implements a non-blocking send
public synchronized void send(Object item) throws RemoteException {
queue.addElement(item);
System.out.println("Producer entered " + item + " size = " + queue.size());
}
1.37
RMI 프로그램 예제
MessageQueueImpl.java (2)

// This implements a non-blocking receive
public synchronized Object receive() throws RemoteException {
Object item;
if (queue.size() == 0)
return null;
else {
item = queue.firstElement();
queue.removeElementAt(0);
System.out.println("Consumer removed " + item + " size = " + queue.size());
return item;
}
}
1.38
RMI 프로그램 예제
MessageQueueImpl.java (3)
public static void main(String args[]) {
System.setSecurityManager(new RMISecurityManager());

try {
MessageQueue server = new MessageQueueImpl();
Naming.rebind("//127.0.0.1/MessageServer", server);
//Naming.rebind("rmi://localhost:1099/MessageServer", server);
System.out.println("Server Bound");
}
catch(Exception e) {
System.err.println(e);
}
}
private Vector queue;
}
1.39
RMI 프로그램 예제
Factory.java (1)

import java.util.*;
import java.rmi.*;
public class Factory {
public Factory() {
// remote object
MessageQueue mailBox;
System.setSecurityManager(new RMISecurityManager());
try {
mailBox =
MessageQueue)Naming.lookup("rmi://127.0.0.1/MessageServer");
// now create the producer and consumer threads
Producer producerThread = new Producer(mailBox);
Consumer consumerThread = new Consumer(mailBox);
producerThread.start();
consumerThread.start();
}
catch (Exception e) {
System.err.println(e);
}
}
1.40
RMI 프로그램 예제
Factory.java (2)

// producer and consumer will call this to nap
public static void napping() {
int sleepTime = (int) (NAP_TIME * Math.random() );
try { Thread.sleep(sleepTime*1000); }
catch(InterruptedException e) { }
}
public static void main(String args[])
{
Factory client = new Factory();
}
private static final int NAP_TIME = 5;
}
1.41
RMI 프로그램 예제

Producer.java
import java.util.*;
class Producer extends Thread{
public Producer(MessageQueue m) {
mbox = m;
} public void run() {
Date message;
while (true)
{
Factory.napping();
// produce an item & enter it into the buffer
message = new Date();
try {
mbox.send(message);
}
catch (Exception e) {
System.err.println(e);
}
}
}
private MessageQueue mbox;
}
1.42
RMI 프로그램 예제

Consumer.java
import java.util.*;
class Consumer extends Thread {
public Consumer(MessageQueue m) {
mbox = m;
}
public void run() {
Date message;
while (true) {
Factory.napping();
// consume an item from the buffer
try {
message = (Date)mbox.receive();
if (message != null)
// Consume the item
;
}
catch (Exception e) {
System.err.println(e);
}
}
}
private MessageQueue mbox;
}
1.43
간단한 Java Applet 프로그램
HTML 파일
<html>
<head><title>간단한 애플릿 예 </title></head>
<body>
<applet code=FirstApplet.class width=400 height=200>
</applet>
</html>

간단한 Applet
import java.applet.* ;
import java.awt.* ;
public class FirstApplet extends Applet {
public void init() {
//initialization code goes here
}
public void paint(Graphics g) {
g.drawString("Java Primer Now Brewing!", 15, 15);
}
}

1.44
간단한 Java Applet 프로그램
import java.applet.* ;
import java.awt.* ;
public class FirstApplet extends Applet {
public void init() {
//initialization code goes here
}
public void paint(Graphics g) {
g.drawString("Java Primer Now Brewing!", 15, 15);
}
}
1.45
일찍 일어나는 새
당신이 새라면
아침에 일찍 일어나야 한다.
그래야 벌레를 잡아먹을 수 있을 테니까.
만일 당신이 새라면
아침에 일찍 일어나라.
하지만 만일
당신이 벌레라면
아주 늦게 일어나야 하겠지.
쉘 실버스타인
1.46