return replyCode;
}
infoArea.Println("HELO response is OK");
infoArea.Println("request MAIL FROM");
//SEND MAIL FROM: SPC <sender> CRLF
out.WriteToStream(SMTPCommand[SMTP_CMD_MAIL_FROM]);
out.WriteToStream(SMTPCommand[SMTP_CMD_SPC]);
out.WriteToStream(senderMail.getText());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
//WAIT FOR RESPONSE ON MAIL FROM
replyCode=waitForTimeout(in);
if (replyCode==0)
{
infoArea.Println("NOT RESPONSE TO HELO ERROR CODE 2");
return 2;
}
if (replyCode==-1)
{
infoArea.Println("UNKNOWN REPLY CODE ERROR CODE 4");
return 4;
}
if (replyCode!=SMTP_RCODE_COMPLETED)
{
infoArea.Println("UNABLE TO COMPLETE REPLY");
return replyCode;
}
infoArea.Println("MAIL FROM response is OK");
infoArea.Println("request RCPT TO");
//SEND RCPT TO: SPC <sender> CRLF
out.WriteToStream(SMTPCommand[SMTP_CMD_RCPT_TO]);
out.WriteToStream(SMTPCommand[SMTP_CMD_SPC]);
out.WriteToStream(reciverMail.getText());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
//WAIT FOR RESPONSE ON RCPT TO
replyCode=waitForTimeout(in);
if (replyCode==0)
{
infoArea.Println("NOT RESPONSE TO HELO ERROR CODE 2");
return 2;
}
if (replyCode==-1)
{
infoArea.Println("UNKNOWN REPLY CODE ERROR CODE 4");
return 4;
}
if ((replyCode!=SMTP_RCODE_COMPLETED) &&
(replyCode!=SMTP_RCODE_FORWARD))
{
infoArea.Println("UNABLE TO COMPLETE REPLY");
return replyCode;
}
infoArea.Println("RCPT TO response is OK");
//TRY TO SEND TO CC
if ((ccMail.getText().length())>0)
{
infoArea.Println("request CC RCPT TO");
//SEND RCPT TO: SPC <sender> CRLF
out.WriteToStream(SMTPCommand[SMTP_CMD_RCPT_TO]);
out.WriteToStream(SMTPCommand[SMTP_CMD_SPC]);
out.WriteToStream(ccMail.getText());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
//WAIT FOR RESPONSE ON RCPT TO
replyCode=waitForTimeout(in);
if (replyCode==0)
{
infoArea.Println("NOT RESPONSE TO HELO ERROR CODE 2");
return 2;
}
if (replyCode==-1)
{
infoArea.Println("UNKNOWN REPLY CODE ERROR CODE 4");
return 4;
}
if ((replyCode!=SMTP_RCODE_COMPLETED) &&
(replyCode!=SMTP_RCODE_FORWARD))
{
infoArea.Println("UNABLE TO COMPLETE CC");
}
else
{
infoArea.Println("CC.RCPT TO response is OK");
}
}
//TRY TO SEND TO BCC
if ((bccMail.getText().length())>0)
{
//SEND RCPT TO: SPC <sender> CRLF
out.WriteToStream(SMTPCommand[SMTP_CMD_RCPT_TO]);
out.WriteToStream(SMTPCommand[SMTP_CMD_SPC]);
out.WriteToStream(bccMail.getText());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
//WAIT FOR RESPONSE ON RCPT TO
replyCode=waitForTimeout(in);
if (replyCode==0)
{
infoArea.Println("NOT RESPONSE TO HELO ERROR CODE 2");
return 2;
}
if (replyCode==-1)
{
infoArea.Println("UNKNOWN REPLY CODE ERROR CODE 4");
return 4;
}
if ((replyCode!=SMTP_RCODE_COMPLETED) &&
(replyCode!=SMTP_RCODE_FORWARD))
{
infoArea.Println("UNABLE TO COMPLETE BCC");
}
else
{
infoArea.Println("BCC.RCPT TO response is OK");
}
}
infoArea.Println("request DATA");
//SEND DATA CRLF
out.WriteToStream(SMTPCommand[SMTP_CMD_DATA]);
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
//WAIT FOR RESPONSE ON DATA
replyCode=waitForTimeout(in);
if (replyCode==0)
{
infoArea.Println("NOT RESPONSE TO HELO ERROR CODE 2");
return 2;
}
if (replyCode==-1)
{
infoArea.Println("UNKNOWN REPLY CODE ERROR CODE 4");
return 4;
}
if (replyCode!=SMTP_RCODE_MAIL_START)
{
infoArea.Println("UNABLE TO COMPLETE REPLY");
return replyCode;
}
infoArea.Println("DATA response is OK");
infoArea.Println("request DATA");
//SEND mail content CRLF.CRLF
out.WriteToStream("Subject: "+subjectMail.getText());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
out.WriteToStream("From: "+senderMail.getText());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
out.WriteToStream("To: "+reciverMail.getText());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
out.WriteToStream("Date: "+today.toString());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
out.WriteToStream(bodyMail.getText());
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF_CRLF]);
//WAIT FOR RESPONSE ON mail content CRLF.CRLF
replyCode=waitForTimeout(in);
if (replyCode==0)
{
infoArea.Println("NOT RESPONSE TO HELO ERROR CODE 2");
return 2;
}
if (replyCode==-1)
{
infoArea.Println("UNKNOWN REPLY CODE ERROR CODE 4");
return 4;
}
if (replyCode!=SMTP_RCODE_COMPLETED)
{
infoArea.Println("UNABLE TO COMPLETE REPLY");
return replyCode;
}
infoArea.Println("mail content response is OK");
infoArea.Println("request QUIT");
//SEND QUIT CRLF
out.WriteToStream(SMTPCommand[SMTP_CMD_QUIT]);
out.WriteToStream(SMTPCommand[SMTP_CMD_CRLF]);
//WAIT FOR RESPONSE (WAIT_TIMEOUT) millis
// NOT RESPONSE TO QUIT ERROR CODE 3
replyCode=waitForTimeout(in);
if (replyCode==0)
{
infoArea.Println("NOT RESPONSE TO QUIT ERROR CODE 3");
return 3;
}
if (replyCode==-1)
{
infoArea.Println("UNKNOWN REPLY CODE ERROR CODE 4");
return 4;
}
if (replyCode!=SMTP_RCODE_CLOSING)
{
infoArea.Println("UNCLOSED CONNECTION REPLY");
return replyCode;
}
infoArea.Println("QUIT response is BYE");
infoArea.Println("end of SMTP transaction");
// TRANSACTION OK ERROR CODE 0
return 0;
}
//TRANSACTION RULES
/* S - Send
F - Fail
E - Error
CONNECTION ESTABLISHMENT
S: 220
F: 421
HELO
S: 250
E: 500, 501, 504, 421
MAIL
S: 250
F: 552, 451, 452
E: 500, 501, 421
RCPT
S: 250, 251
F: 550, 551, 552, 553, 450, 451, 452
E: 500, 501, 503, 421
DATA
I: 354 -> data -> S: 250
F: 552, 554, 451, 452
F: 451, 554
E: 500, 501, 503, 421
RSET
S: 250
E: 500, 501, 504, 421
SEND
S: 250
F: 552, 451, 452
E: 500, 501, 502, 421
SOML
S: 250
F: 552, 451, 452
E: 500, 501, 502, 421
SAML
S: 250
F: 552, 451, 452
E: 500, 501, 502, 421
VRFY
S: 250, 251
F: 550, 551, 553
E: 500, 501, 502, 504, 421
EXPN
S: 250
F: 550
E: 500, 501, 502, 504, 421
HELP
S: 211, 214
E: 500, 501, 502, 504, 421
NOOP
S: 250
E: 500, 421
QUIT
S: 221
E: 500
TURN
S: 250
F: 502
E: 500, 503 */
TextField smtpServer;
TextField smtpPort;
TextField senderMail;
TextField reciverMail;
TextField ccMail;
TextField bccMail;
TextField subjectMail;
InfoBox bodyMail;
InfoBox infoArea;
Button sendMail;
Button clearMail;
Button quitProgram;
//******************************************************************
SMTPprotocol()
{
super("SMTP Protocol Test v.1.0 by Tair Abdurman");
setBackground(Color.lightGray);
setLayout(new FlowLayout());
//******************************************************************
smtpServer=new TextField("smtp.yourserver.com",50);
smtpPort=new TextField("25",10);
senderMail=new TextField("",80);
reciverMail=new TextField("",80);
ccMail=new TextField("",80);
bccMail=new TextField("",80);
subjectMail=new TextField("SMTP deneme",80);
add(new Label("SMTP Server:"));
add(smtpServer);
add(new Label("SMTP Port:"));
add(smtpPort);
add(new Label("From: "));
add(senderMail);
add(new Label("To : "));
add(reciverMail);
add(new Label("Cc : "));
add(ccMail);
add(new Label("Bcc : "));
add(bccMail);
add(new Label("Subject :"));
add(subjectMail);
add(new Label("Content : "));
bodyMail=new InfoBox(5,90);
bodyMail.setEditable(true);
add(bodyMail);
sendMail=new Button("send");
clearMail=new Button("clear");
quitProgram=new Button("quit");
add(sendMail);
add(clearMail);
add(quitProgram);
infoArea=new InfoBox(4,90);
add(infoArea);
//******************************************************************
resize(700,450);
show();
infoArea.Println("ready ...");
}
//ON QUIT PROGRAM
void onQuit()
{
infoArea.Println("quit programm ...");
System.exit(0);
}
//ON CLEAR MAIL
void onClearMail()
{
infoArea.Println("clearing mail ...");
bodyMail.Clear();
}
//ON SEND MAIL
int onSendMail()
{
String inBuffer;
String outBuffer;
Socket sock;
SMTPInputStream fromServer;
SMTPOutputStream toServer;
int intPort;
//TEST RECIPIENT ADDRESS it must be at once
if (reciverMail.getText().length()<1)
{
infoArea.Println("enter recipient please ...");
return -1;
}
//TEST PORT NUMBER FORMAT and ALERT WHEN NOT 25
intPort=-1;
infoArea.Clear();
infoArea.Println("check port ...");
try
{
intPort=Integer.valueOf(smtpPort.getText()).intValue();
if ((intPort<0) || (intPort>65356))
{
infoArea.Println("invalid port ...");
return -1;
}
if (intPort!=25)
infoArea.Println("attention port is not 25 ...");
infoArea.Println("port number is "+smtpPort.getText());
}
catch(NumberFormatException e)
{
infoArea.Println("invalid port ...");
return -1;
}
//CREATE SMTP CONNECTION
infoArea.Println("connect to server ...");
try
{
sock=new Socket(smtpServer.getText(),intPort);
}
catch(IOException e)
{
infoArea.Println("unable to connect(SK) ...");
return -1;
}
//CREATE SERVER STREAMS
//INPUT STREAM
try
{
fromServer=new SMTPInputStream(sock);
}
catch(IOException e)
{
infoArea.Println("unable to connect(IS) ...");
return -1;
}
//OUTPUT STREAM
try
{
toServer=new SMTPOutputStream(sock);
}
catch(IOException e)
{
infoArea.Println("unable to connect(OS) ...");
return -1;
}
infoArea.Println("connected ...");
//Mail Sending
infoArea.Println("sending mail ...");
//*******************************************************************
try
{
int i=doSMTPTransaction(fromServer,toServer);
if (i==0)
infoArea.Println("complete ...");
else
infoArea.Println("error ...");
}
catch(IOException e)
{
infoArea.Println("error ...");
}
//*******************************************************************
//CLOSE SERVER STREAMS
//OUTPUT STREAM
infoArea.Println("disconnect from server ...");
try
{
toServer.Close();
}
catch(IOException e)
{
infoArea.Println("alert OUTPUT STREAM ...");
}
//INPUT STREAM
try
{
fromServer.Close();
}
catch(IOException e)
{
infoArea.Println("alert INPUT STREAM ...");
}
//CLOSE CONNECTION
try
{
sock.close();
infoArea.Println("disconnected ...");
}
catch(IOException e)
{
infoArea.Println("unable to disconnect ...");
return -1;
}
return 0;
}
//EVENT HANDLER
public synchronized boolean handleEvent(Event e)
{
if (e.id==Event.WINDOW_DESTROY)
{
System.exit(0);
return true;
}
else
{
return super.handleEvent(e);
}
}
//ACTION HANDLER
public boolean action(Event evt,Object obj)
{
if (evt.target instanceof Button)
{
String label=(String) obj;
if (label.equals("quit"))
{
onQuit();
}
else if (label.equals("send"))
{
int i=onSendMail();
}
else if (label.equals("clear"))
{
onClearMail();
}
}
return true;
}
//ENTRY POINT FOR CORE CLASS
public static void main(String args[])
{
new SMTPprotocol();
}
}
Java Remote Method Invocation(Java RMI) – Report/Overview
RMI is a technique used in creating client-server applications. If communication with a remote object requires the use of custom sockets, you need to inform the RMI runtime which custom socket factories to use when you export the remote object. When your application exports the object specifying custom socket factories, the RMI runtime will use the corresponding custom RMIServerSocketFactory to create a server socket to accept incoming calls to the remote object. Also, the RMI runtime will create a stub that refers to the corresponding custom RMIClientSocketFactory. This client socket factory will be used to create connections upon initiating a remote invocation to the remote object using the stub.
Java Remote Method Invocation (RMI) doesn’t need to be within the same address space as the calling procedure. The two processes could even be on different systems, as long as there is a network connecting them. Programmers find this technique of use as it avoids the interface details of the network RMI, makes the client-server model a lot more easier to program, manage, and also making it more powerful in the process. When this method is incorporated with RMI, clients can further, make remote calls through a local procedure interface. RMI IS:-
- A cross between remote procedure call and mobile objects
- A server-side object is created, along with a stub object
- Both the server-side object and the stub implement a "well known" interface
- The server-side object remains on the server, and receives and executes remote method calls
- The stub is moved as a mobile object to a client
- The client makes calls on the stub which makes remote calls on the server-side object
To create an RMI application, the following two steps are carried out.
- Firstly, define a remote interface(must be declared as Public)
- Secondly, define constructor that calls supper() and trows
All of the programs need to completed individually.
The two codes of the client/server communicate via the procedures that are specified in the original protocol. The server side registers the procedures that could be called by the client, as well as receiving/returning any data that is required for processing. The client side calls the remote procedure, passes any required data, as well as receiving the returned data.
Transfering an Object via Remote Method Call
This example works under JDK1.1 beta2. It assumes that Stub and Skeleton codes are under the same directory as in Client code. That is, the Stub and Skeleton codes are located local to Client as well as to Server. If they are at other location, Client has to dynamically invoke stub class loading: subtle changes have to be made to make this work.
Objective
Understand how rmi send object across network.
Descriptions
* You have four programs: RemoteInterface.java, RemoteClient.java, RemoteServer.java, and MyObject.java. Client site has RemoteInterface, RemoteClient, and MyObject. Server site has RemoteInterface, RemoteServer, and MyObject.
* MyObject.java: The local object which is transfered across network.
Local object should implement java.io.Serializable to be transferred.
* RemoteInterface.java: Interface defining the remote behavior
* RemoteClient.java: Client program which sends an object to remote server
* RemoteServer.java: Server program which listens to client request, looks at the received object, changes the data field of the object , and send the object back to the client
* Client and Server program can reside in different hosts. But all the codes are under the same directory. For Client and Server codes to work from different directories, but still to bind codes statically, Client site has to have Stub and Skeleton code.
To compile:
javac RemoteClient.java
javac RemoteServer.java
rmic RemoteServer
* To run the server code, you first have to run the Registry.
rmiregistry &
java RemoteServer
To run the client code, you have to specify the host name of the server at the command argument.
java RemoteClient host_name
Program
* MyObject.java
public class MyObject implements java.io.Serializable {
private int x;
private String msg;
public MyObject (String s) {
msg = s;
x = msg.length();
}
public int lenMsg() {
return x;
}
public String retMsg() {
return msg;
}
public void setMsg(String s) {
msg = s;
}
}
* RemoteInterface.java
public interface RemoteInterface extends java.rmi.Remote {
MyObject msgsend (MyObject message) throws java.rmi.RemoteException;
}
* RemoteClient.java
import java.rmi.*;
public class RemoteClient {
public static void main(String args[]) {
System.setSecurityManager(new RMISecurityManager());
try {
RemoteInterface server = (RemoteInterface)
Naming.lookup("rmi://" + args[0] + "/" + "ObjectServer Test");
MyObject msgObj = new MyObject("Hello There");
MyObject retObj = server.msgsend(msgObj);
System.out.println("The server says :\n" + retObj.retMsg());
} catch (Exception e){
System.out.println("Error while performing RMI");
}
}
}
* RemoteServer.java
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
public class RemoteServer extends UnicastRemoteObject
implements RemoteInterface{
String name;
public RemoteServer(String name) throws RemoteException{
super();
this.name = name;
}
public MyObject msgsend(MyObject message) throws RemoteException{
System.out.println("msg got:" + message.retMsg() +
", msg length:" + message.lenMsg());
message.setMsg("My Name is:" + name + ",thanks for your message:"
+ message.retMsg());
return message;
}
public static void main (String args[]){
System.setSecurityManager (new RMISecurityManager());
try{
String myName = "ObjectServer Test";
RemoteServer theServer = new RemoteServer (myName);
Naming.rebind(myName,theServer);
} catch (Exception e){
System.out.println("An Exception occured while creating server");
}
}
}
Java RMI Example
This simple example is (in slightly modified form) from Client/Server Programming with Java and CORBA by Robert Orfali and Dan Harkey. The goal of the example is to develop a simple counter application. The server object maintains a counter which can be incremented by its clients. In the book, the example serves several purposes. First, it is easily understood and allows the reader to focus on the component technology being used. Second, round-trip network performance (e.g. a ping) for the component technology can be roughly measured by having the client invoke the server n times and computing the elapsed time divided by n.
We start out by defining the interface for the serverside program:
CountRMI.java
public interface CountRMI extends java.rmi.Remote {
public int sum() throws java.rmi.RemoteException;
public void sum(int _val) throws java.rmi.RemoteException;
public int increment() throws java.rmi.RemoteException;
}
This file defines an interface called CountRMI, which is used to define the behaviour expected from a CountRMI server. Just as a Corba IDL file describes the interface a server implements, RMI server classes require that the methods they make available to the world are defined (as public) in an interface definition. As presented the interface defines a clas, which has an integer attribute, which can be retrieved and set. The attribute is incremented by the method increment. The class implements a noteworthy interface, java.rmi.Remote, which indicates that classes implementing CountRMI will be residing on a server. The Remote interface does not define methods - rather it is used to flag that this is an remote class.
The server is in:
CountRMIImpl.java
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
public class CountRMIImpl extends UnicastRemoteObject implements CountRMI {
private int sum;
public CountRMIImpl(String name) throws RemoteException {
super();
try {
Naming.rebind(name, this);
sum = 0;
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
e.printStackTrace();
}
}
public int sum() throws RemoteException {
return sum;
}
public void sum(int _val) throws RemoteException {
sum = _val;
}
public int increment() throws RemoteException {
return ++sum;
}
}
There are several interesting things in this program. The CountRMIImpl not only implements CountRMI as could be expected, but also extends java.rmi.UnicastRemoteObject. UnicastRemoteObject implements the semantics a remote object with the following characteristics:
1. A reference to an UnicastRemoteObject is only valid while the creator process exists
2. Communication between client and server is done through streams over a TCP connection
In order to enable this implementation for RMI use, stub and skeleton classes must be created, which is done in the following manner:
$ rmic CountRMIImpl
$ dir CountRMIImpl*
-rw-r--r-- 1 544 everyone 1109 Dec 15 00:08 CountRMIImpl.class
-rw-r--r-- 1 544 everyone 725 Dec 15 00:06 CountRMIImpl.java
-rw-r--r-- 1 544 everyone 1975 Dec 15 01:23 CountRMIImpl_Skel.class
-rw-r--r-- 1 544 everyone 2465 Dec 15 01:23 CountRMIImpl_Stub.class
The client looks like this:
CountRMIClient.java
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
public class CountRMIClient {
public static void main(String args[]) {
try {
CountRMI myCount = (CountRMI)Naming.lookup("rmi://" + args[0] + "/" + "my CountRMI");
// Set Sum to initial value of 0
System.out.println("Setting Sum to 0");
myCount.setSum(0);
// Calculate Start time
long startTime = System.currentTimeMillis();
// Increment 1000 times
System.out.println("Incrementing");
for (int i = 0 ; i < 1000 ; i++ ) {
myCount.increment();
}
// Calculate stop time; print out statistics
long stopTime = System.currentTimeMillis();
System.out.println("Avg Ping = " + ((stopTime - startTime)/1000f) + " msecs");
System.out.println("Sum = " + myCount.getSum());
} catch(Exception e) {
System.err.println("System Exception" + e);
}
System.exit(0);
}
}
CountRMIClient starts out by locating a remote object implementing the CountRMI interface. The program is given the machine name whereon this object resides as parameter, and thus proceeds to get a reference to an object called 'my CountRMI' on the aforementioned machine. Once this has been accomplished the rest of the program is quite simple ordinary Java code, calculating the mean time of incrementing a counter.
Given the interface, the object implementing it, and the client to use it, we now only need the server to instantiate the remote object:
CountRMIServer.java
// CountRMIServer.java
import java.rmi.*;
import java.rmi.server.*;
public class CountRMIServer
{
public static void main(String args[]) {
// Create and install the security manager
System.setSecurityManager(new RMISecurityManager());
try {
// Create CountRMIImpl
CountRMIImpl myCount = new CountRMIImpl("my CountRMI");
System.out.println("CountRMI Server ready.");
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
e.printStackTrace();
}
}
}
The CountRMIServer starts out by installing a RMI security manager to protect itself from (possibly hostile) foreign classes. It then instantiates the implementation of CountRMI and gives it name 'my CountRMI'.
In order to run this under Windows NT, a developer would write the following:
$ start rmiregistry
$ start CountRMIServer
$ start java CountRMIServer
$ java CountRMIClient talisker.daimi.aau.dk
Symantec Java! JustInTime Compiler Version 210.063 for JDK 1.1.3
Copyright (C) 1996-97 Symantec Corporation
Setting Sum to 0
Incrementing
Avg Ping = 1.016 msecs
Sum = 1000
This example is thus completed.