Internet Programming with Java Course
2.4.Ïðèìåð: Ðàçðàáîòêà íà chat àïëåò
/**
* Chat applet client for Nakov Chat Server.
* Author: Nikolay Nedyalkov, 2002
*
* ChatApplet class provides applet-based graphical user interface
* for the clients of NakovChatServer.
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.Vector;
import java.util.Enumeration;
public class ChatApplet extends Applet implements ActionListener, MouseListener {
boolean isStandalone = false;
private ChatClient cl = new ChatClient (this);
private PopupMenu popupMenu1 = new PopupMenu ();
private MenuItem menuItem1 = new MenuItem ();
private MenuItem menuItem2 = new MenuItem ();
private Vector allUsers = new Vector ();
private Vector deniedUsers = new Vector ();
private boolean isConnected = false;
private TextField textField1 = new TextField();
private Button connectButton = new Button ();
private Button disconnectButton = new Button ();
private Button sendButton = new Button ();
private Button clearButton = new Button ();
private Button exitButton = new Button ();
public TextArea textArea1 = new TextArea();
public List list1 = new List();
public void setConnected(boolean aConnected) {
isConnected = aConnected;
}
public boolean getConnected() {
return isConnected;
}
/**
* Method is called from ChatClient to get reference to ChatApplet.textArea1.
* @return java.awt.TextArea
*/
public TextArea getTextArea () {
return textArea1;
}
/**
* Method is called from ChatClient to get reference to ChatApplet.list1.
* @return java.awt.List
*/
public List getList () {
return list1;
}
/**
* Method is called from ChatClient to register anUser in allUsers vector
* and list1 visual control.
* @param anUser - user to be included.
*/
public synchronized void addUser (String anUser) {
if (!allUsers.contains(anUser)) {
allUsers.addElement (anUser);
list1.add (anUser);
}
}
/**
* Method is called from ChatClient to append given message to the
* ChatApplet's TextArea. It also checks whether anUser is in our
* Ignore list and ignores the message in this case.
* @param anUser - user that have sent the message
* @param aText - message to be appened to the applet's TextArea
*/
public synchronized void addText (String aText, String anUser) {
if (!deniedUsers.contains(anUser)) {
textArea1.append (aText + "\n");
}
}
public synchronized void addSystemMessage(String aText) {
textArea1.append(aText + "\n");
}
/**
* Applet life cycle initiliazation.
*/
public void init() {
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**
* Component initialization.
* @throws Exception
*/
private void jbInit() throws Exception {
this.setLayout (null);
// -- Begin buttons section
sendButton.setLabel("Send");
sendButton.setBounds (new Rectangle(316, 245, 68, 23));
sendButton.addActionListener (this);
this.add(sendButton);
connectButton.setLabel("connect");
connectButton.setBounds(new Rectangle(34, 270, 95, 22));
connectButton.addActionListener(this);
this.add(connectButton, null);
disconnectButton.addActionListener(this);
disconnectButton.setBounds(new Rectangle(175, 270, 108, 22));
disconnectButton.setLabel("disconnect");
this.add(disconnectButton, null);
clearButton.setLabel("Clear");
clearButton.addActionListener(this);
clearButton.setBounds(new Rectangle(316, 270, 68, 23));
this.add(clearButton, null);
exitButton.setBackground(Color.gray);
exitButton.setForeground(Color.lightGray);
exitButton.setLabel("Q");
exitButton.setBounds(new Rectangle(388, 245, 32, 48));
exitButton.addActionListener(this);
this.add(exitButton, null);
// -- End buttons section
// -- Begin edit controls
textField1.setBounds(new Rectangle(10, 245, 303, 23));
textField1.addActionListener(this);
textField1.setBackground(Color.lightGray);
this.add(textField1, null);
textArea1.setBounds(new Rectangle(10, 10, 303, 233));
textArea1.setBackground(Color.lightGray);
this.add(textArea1, null);
// -- End edit controls
// -- Begin menus section
popupMenu1.setLabel("User menu");
menuItem1.setLabel("Ignore user");
menuItem1.setActionCommand ("BAN");
menuItem1.addActionListener (this);
menuItem2.setLabel("Deignore user");
menuItem2.setActionCommand ("UNBAN");
menuItem2.addActionListener (this);
popupMenu1.add(menuItem1);
popupMenu1.addSeparator();
popupMenu1.add(menuItem2);
// -- End menus section
list1.setBounds(new Rectangle(316, 11, 104, 233));
list1.add (popupMenu1);
list1.addActionListener (this);
list1.addMouseListener (this);
list1.setBackground(Color.lightGray);
this.add (popupMenu1);
this.add(list1, null);
this.setBackground(Color.cyan);
}
/**
* Method sends aMessage to server through ChatClient.
* @param aMessage
*/
public void sendMessage (String aMessage) {
cl.getOutput().println (aMessage);
cl.getOutput().flush();
}
/**
* Method handles ActionEvent event, registered by "this" Action listener.
* @param ae - ActionEvent which we used to indicate "sender".
*/
public void actionPerformed (ActionEvent ae) {
if (ae.getSource().equals(textField1)) {
// catch ActionEvents coming from textField1
sendButtonPressed();
} else if (ae.getSource().equals(connectButton)) {
// catch ActionEvents coming connect button from textField1
if (!isConnected) {
addSystemMessage("Connecting...");
isConnected = cl.connect();
} else {
addSystemMessage("Already connected.");
}
} else if (ae.getSource().equals(sendButton)) {
// catch ActionEvents coming send button from textField1
sendButtonPressed();
} else if (ae.getSource().equals(menuItem1)) {
// catch ActionEvents comming from popupMenu->menuItem1->"Ignore"
String selectedUser = list1.getSelectedItem();
deniedUsers.addElement (selectedUser);
addSystemMessage("User added to ban list.");
} else if (ae.getSource().equals(menuItem2)) {
// catch ActionEvents comming from popupMenu->menuItem1->"Deignore"
String selectedUser = list1.getSelectedItem();
if (!deniedUsers.removeElement (selectedUser))
addSystemMessage("No such user in ban list.");
else
addSystemMessage("User removed from ban list.");
} else if (ae.getSource().equals(clearButton)) {
// catch ActionEvents comming from clear button
textArea1.setText("");
} else if (ae.getSource().equals(disconnectButton)) {
// catch ActionEvents comming from disconnect button
cl.disconnect();
} else if (ae.getSource().equals(exitButton)) {
// catch ActionEvents comming from exit button
System.exit(0);
}
}
private void sendButtonPressed() {
if (!isConnected) {
textArea1.append("Please connect first.\n");
return;
}
String text = textField1.getText();
if (text.equals(""))
return;
sendMessage (text);
textField1.setText ("");
}
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
/**
* Method handles mousePressed event, registered by "this" MouseListener.
* @param e MouseEvent
*/
public void mousePressed(MouseEvent e) {
// register when user pressed right mouse button
// - e.getModifiers()==e.BUTTON3_MASK -
// and when is "mouse down" - e.MOUSE_PRESSED==501.
if ((e.getModifiers()==e.BUTTON3_MASK)&&(e.MOUSE_PRESSED==501)) {
popupMenu1.show (list1, e.getX(), e.getY());
}
}
}
/**
* Chat applet client for Nakov Chat Server.
* Author: Nikolay Nedyalkov, 2002
*
* ChatClient class handles the communication with the chat server.
*/
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.Hashtable;
public class ChatClient
{
public static final int SERVER_PORT = 2002;
private Socket m_Socket = null;
private BufferedReader in = null;
private PrintWriter out = null;
private ChatApplet m_Applet;
/**
* Constructor initialize ChatClient and sets ChatApplet refferences.
*/
public ChatClient (ChatApplet anApplet) {
this.m_Applet = anApplet;
}
/**
* Method is called from ChatApplet.
* @return PrintWriter reference to server connection.
*/
public PrintWriter getOutput () {
return out;
}
/**
* Method is called from ChatApplet.
* @return BufferedReader reference to server connection.
*/
public BufferedReader getInput () {
return in;
}
/**
* Method is called from ChatApplet to establish connection to NakovChatServer.
* In case of the applet is started locally from a file (not from a web server),
* "localhost" is used as taget server, otherwise getCodeBase().getHost() is used.
*/
public boolean connect () {
boolean successfull = true;
String serverHost = m_Applet.getCodeBase().getHost();
if (serverHost.length()==0) {
m_Applet.addSystemMessage("Warning: Applet is loaded from a local file,");
m_Applet.addSystemMessage("not from a web server. Web browser's security");
m_Applet.addSystemMessage("will probably disable socket connections.");
serverHost = "localhost";
}
try {
m_Socket = new Socket(serverHost, SERVER_PORT);
in = new BufferedReader(
new InputStreamReader(m_Socket.getInputStream()));
out = new PrintWriter(
new OutputStreamWriter(m_Socket.getOutputStream()));
m_Applet.addSystemMessage("Connected to server " +
serverHost + ":" + SERVER_PORT);
} catch (SecurityException se) {
m_Applet.addSystemMessage("Security policy does not allow " +
"connection to " + serverHost + ":" + SERVER_PORT);
successfull = false;
} catch (IOException e) {
m_Applet.addSystemMessage("Can not establish connection to " +
serverHost + ":" + SERVER_PORT);
successfull = false;
}
// Create and start Listener thread
Listener listener = new Listener(m_Applet, in);
listener.setDaemon(true);
listener.start();
return successfull;
}
public void disconnect() {
if (!m_Applet.getConnected()) {
m_Applet.addSystemMessage("Can not disconnect. Not connected.");
return;
}
m_Applet.setConnected(false);
try {
m_Socket.close();
} catch (IOException ioe) {
}
m_Applet.addSystemMessage("Disconnected.");
}
/**
* Listener class - thread is used for receiving data that comes from
* the server and then "forward" it to ChatApplet.
*/
class Listener extends Thread
{
private BufferedReader mIn;
private ChatApplet mCA;
/**
* Constructor initiliaze InputStream, and ChatApplet reference
* @param aCA - ChatApplet reference
* @param aIn - InputStream from server connection
*/
public Listener (ChatApplet aCA, BufferedReader aIn) {
mCA = aCA;
mIn = aIn;
}
public void run() {
try {
while (!isInterrupted()) {
String message = mIn.readLine();
int colon2index = message.indexOf(":",message.indexOf(":")+1);
String user = message.substring(0, colon2index-1);
mCA.addText (message, user);
mCA.addUser (user);
}
} catch (Exception ioe) {
if (m_Applet.getConnected())
m_Applet.addSystemMessage("Communication error.");
}
m_Applet.setConnected(false);
}
}
}
NakovChatServer å äîñòúïåí îò ëåêöèÿ 1.9 (Ðàçðàáîòêà íà chat êëèåíò/ñúðâúð).
Çà äà èçïúëíèì chat àïëåòà å íåîáõîäèìî äà íàïðàâèì HTML ñòðàíèöà, êîÿòî ãî ñúäúðæà êàòî îáåêò. Íàïðèìåð ìîæåì äà èçïîëçâàìå ñëåäíàòà (ChatApplet.html):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Chat Applet</title>
</head>
<body>
ChatApplet will appear below in a Java enabled browser.<br>
<applet
codebase = "."
code = "ChatApplet.class"
name = "TestApplet"
width = "430"
height = "300"
hspace = "0"
vspace = "0"
align = "middle"
>
</applet>
</body>
</html>
Çà äà èçïúëíèì àïëeòà â AppletViewer å äîñòàòú÷íî äà ãî êîìïèëèðàìå è äà ãî ñòàðòèðàìå ñ ïðîãðàìàòà appletviewer, íàìèðàùà ñå â binäèðåêòîðèÿòà íà íàøàòà èíñòàëàöèÿ íà JDK:
C:\Projects\ChatApplet>
set
PATH=%PATH%;C:\jdk1.3.1\bin
C:\Projects\ChatApplet>
javac *.java
C:\Projects\ChatApplet>
appletviewer
ChatApplet.html
Çà äà ãî èçïúëíèì, îáà÷å â íàøèÿ web-áðàóçúð (íàïðèìåð â Internet Explorer 5.0), å íåîáõîäèìî äà ñòàðòèðàìå íÿêàêúâ web-ñúðâúð è äà ïîèñêàìå ñòðàíèöàòà ñ àïëåòà îò òîçè ñúðâúð ÷ðåç URL-òî, îò êîåòî òÿ å äîñòúïíà.  äèðåêòîðèÿòà, â êîÿòî ñå íàìèðà òàçè ñòðàíèöà, òðÿáâà äà ñå íàìèðàò è âñè÷êè .classôàéëîâå, íåîáõîäèìè çà ðàáîòàòà íà àïëåòà. Òðÿáâà äà ñìå íàÿñíî, ÷å àêî îòâîðèì ëîêàëíî êàòî ôàéë (íå êàòî URL)ñòðàíèöàòà ChatApplet.html, àïëåòúò ùå ñå ñòàðòèðà, íî íÿìà äà èìà ïðàâî äà îòâàðÿ ñîêåòè. Òîâà å òàêà îò ñúîáðàæåíèÿ çà ñèãóðíîñòè å ñúâñåì àäåêâàòíà ïîëèòèêà íà çàùèòà, êîÿòî web-áðàóçúðèòå ïðèëàãàò. Êîãàòî àïëåòúò å ñòàðòèðàí îò ñòðàíèöà, çàðåäåíà îò ëîêàëåí ôàéë, getCodeBase().getHost()âðúùà ïðàçåí íèçè àïëåòúò íÿìà ïðàâî äà îòâàðÿ íèêàêâè ñîêåòè. Êîãàòî àïëåòúò å ñòàðòèðàí îò ñòðàíèöà, çàðåäåíà îò íÿêîé web-ñúðâúð, getCodeBase().getHost() âðúùà èìåòî íà òîçè ñúðâúð èëè IP àäðåñà ìó è àïëåòúò èìà ïðàâî äà îòâàðÿ ñîêåòè êúì íåãî. Çàòîâà,çà äà òåñòâàìå àïëåòè â åñòåñòâåíàòà èì ñðåäà (web-áðàóçúðúò), íè å íåîáõîäèì äîñòúï äî íÿêàêúâ web-ñúðâúð, íà êúäåòî äà ãè ïóáëèêóâàìå.