Смекни!
smekni.com

Java технологія и основні риси та перспективи застосування (стр. 2 из 3)

Доступність інструментарію та ефективність розробок.

Зазначена вище простота програмування на Java є причиною того, що розробки на Java коштуватимуть дешевше аналогічних на більш потужніх мовах програмування. Цьому ж сприяє і переносимість програм на Java, оскільки ліквідуються витрати пов’язані з адаптацією програми на конкретній платформі. До того ж інтегровані програми-оболонки для розробки Java програм коштують набагато дешевше ( 70-100$ ) ніж аналогічні продукти C++, Delphi ( ~1000$). А набір інструментарію для пакетної компіляції Java програм JDK (Java Development Kit) є взагалі freeware. Тому платформу Java можна рекомендувати як ідеальну для створення некомерційних програмних продуктів, зокрема для галузі освіти.

Перспективи застосування.

Програми на Java можуть знайти різне застосування в навчальному процесі: інтерактивні навчаючі програми (HTML в поєднанні з Java), програми-тести і особливо ділові ігри. Додаткові переваги можна отримати, якщо пистати ці програми у вигляді аплетів, які ініціалізуються з Web сервера внутрішньої мережі Intranet. В такий спосіб можна уникнути інсталяції програми на багатьох комп’ютерах - користувач просто запускає Web-броузер і загружає потрібну сторінку. Для тестових програм, написаних на Java з викориситанням архітектури клієнт/сервер можна підвищити ступінь конфіденційності. База даних тестових запитань знаходиться на сервері в каталозі з обмеженим доступом. Коли користувач загружає аплет, він автоматично підключається до програми-сервера, яка виконується на сервері і може видавати запитання з бази даних у відповідь на запит користувача. В такий спосіб унеможливлюється викрадення бази даних, за умови відсутності фізичного доступу до серверу у користувачів.

Окреме питання - навчальні ділові ігри. Під такою грою розумітимем гру, за участю кількох користувачів, в якій мається на увазі динамічний обмін інформацією між ними. Система безпеки Java накладає обмеження, внаслідок якого аплет може встановлювати з’єднання лише з хостом, з якого він був загружений і ні з яким більше. Але це обмеження легко обходиться: на сервері виконується програма-сервер, з якою з’єднуються усі клієнти і через яку здійснюється обмін інформацією. Таким чином така програма повинна мати архітектуру клієнт/сервер. В якості приклада наведу спрощену chat-програму. В ній реалізовані базові засоби для створення ділової гри.

Серверна частина програми взята з книги Нотон П. Шилдт Г. «Полный справочник по Java»:-Киев, «Диалектика», 1997 і є практично універсальною для програм такого класу. Можливе легке доопрацювання цієї програми в бік розширення кількості протокольних команд. Клієнтська частина була написана мною. Програма працює наступним чином: користувач запускає аплет із сервера, вводить свій ідентифікатор і бачить перелік ідентифікаторів користувачів, які під’єднані до сервера. Після чого користувач має змогу обмінюватись повідомленнями з іншими. Користувач одержує повідомлення в разі під’єднання або від’єднання користувачів.

Програма складається з 4 класів: Server, ClientConnection, Client та ServerConnection. Перші 2 класи відносяться до серверної частини, другі 2 - до клієнтської.

Клас Server:

import java.net.*;

import java.io.*;

import java.util.*;

public class Server implements Runnable {

private int port = 6564;

private Hashtable idcon = new Hashtable();

private int id = 0;

static final String CRLF = "\r\n";

synchronized void addConnection(Socket s) {

ClientConnection con = new ClientConnection(this, s, id);

id++;

}

synchronized void set(String the_id, ClientConnection con) {

idcon.remove(the_id) ;

con.setBusy(false);

Enumeration e = idcon.keys();

while (e.hasMoreElements()) {

String id = (String)e.nextElement();

ClientConnection other = (ClientConnection) idcon.get(id);

if (!other.isBusy())

con.write("add " + other + CRLF);

}

idcon.put(the_id, con);

broadcast(the_id, "add " + con);

}

synchronized void sendto(String dest, String body) {

ClientConnection con = (ClientConnection)idcon.get(dest);

if (con != null) {

con.write(body + CRLF);

}

}

synchronized void broadcast(String exclude, String body) {

Enumeration e = idcon.keys();

while (e.hasMoreElements()) {

String id = (String)e.nextElement();

if (!exclude.equals(id)) {

ClientConnection con = (ClientConnection) idcon.get(id);

con.write(body + CRLF);

}

}

}

synchronized void delete(String the_id) {

broadcast(the_id, "delete " + the_id);

}

synchronized void kill(ClientConnection c) {

if (idcon.remove(c.getId()) == c) {

delete(c.getId());

}

}

public void run() {

try {

ServerSocket acceptSocket = new ServerSocket(port);

System.out.println("Server listening on port " + port);

while (true) {

Socket s = acceptSocket.accept();

addConnection(s);

}

} catch (IOException e) {

System.out.println("accept loop IOException: " + e);

}

}

public static void main(String args[]) {

new Thread(new Server()).start();

try {

Thread.currentThread().join();

} catch (InterruptedException e) {

}

}

}

Цей невеликий клас реалізує програму-сервер. Точка вхолу програми - функція main. В програмі створюється головний потік, в якому створюється об’єкт стандартного класу ServerSocket. Цей об’єкт приєднується до певного порта і в циклі здійснюється перевірка на підключення клієнта до порта. В разі такого підключення створюється об’єкт типу ClientConnection, в якому реалізований потік по опитуванню сокета, до якого підключений клієнт, та обробка протокольних команд. Клас Server є універсальним і нічого не знає про повідомлення, якими обмінюються гравці (клієнти). В ньому реалізоване лише приєднання/від’єднання клієнтів, надсилання строки певному клієнту та функція broadcast яка, як зрозуміло з назви, надсилає повідомлення усім зареєстрованим клієнтам.

Клас ClientConnection:

import java.net.*;

import java.io.*;

import java.util.*;

class ClientConnection implements Runnable {

private Socket sock;

private DataInputStream in;

private OutputStream out;

private String host;

private Server server;

private static final int bufsize = 8192;

private byte buffer[] = new byte[bufsize];

private static final String CRLF = "\r\n";

private String name = null;

private String id;

private boolean busy = false;

public ClientConnection(Server srv, Socket s, int i) {

try {

server = srv;

sock = s;

in = new DataInputStream(s.getInputStream());

out = s.getOutputStream();

host = s.getInetAddress().getHostName();

id = "" + i;

// tell the new one who it is...

write("id " + id + CRLF);

new Thread(this).start();

} catch (IOException e) {

System.out.println("failed ClientConnection " + e);

}

}

public String toString() {

return id + " " + host + " " + name;

}

public String getHost() {

return host;

}

public String getId() {

return id;

}

public boolean isBusy() {

return busy;

}

public void setBusy(boolean b) {

busy = b;

}

public void close() {

server.kill(this);

try {

sock.close(); // closes in and out too.

} catch (IOException e) {

}

}

public void write(String s) {

byte buf[] = new byte[s.length()];

s.getBytes(0, buf.length, buf, 0);

try {

out.write(buf, 0, buf.length);

} catch (IOException e) {

close();

}

}

private String readline() {

try {

return in.readLine();

} catch (IOException e) {

return null;

}

}

static private final int NAME = 1;

static private final int QUIT = 2;

static private final int TO = 3;

static private final int DELETE = 4;

static private Hashtable keys = new Hashtable();

static private String keystrings[] = {

"", "name", "quit", "to", "delete"

};

static {

for (int i = 0; i < keystrings.length; i++)

keys.put(keystrings[i], new Integer(i));

}

private int lookup(String s) {

Integer i = (Integer) keys.get(s);

return i == null ? -1 : i.intValue();

}

public void run() {

String s;

StringTokenizer st;

out:

while ((s = readline()) != null) {

st = new StringTokenizer(s);

String keyword = st.nextToken();

switch (lookup(keyword)) {

default:

System.out.println("bogus keyword: " + keyword + "&bsol;r");

break;

case NAME:

name = st.nextToken() +

(st.hasMoreTokens() ? " " + st.nextToken(CRLF) : "");

System.out.println("[" + new Date() + "] " + this + "&bsol;r");

server.set(id, this);

break;

case QUIT:

break out;

case TO:

String dest = st.nextToken();

String body = st.nextToken(CRLF);

server.sendto(dest, body);

break;

case DELETE:

busy = true;

server.delete(id);

break;

}

}

close();

}

}

Клас ClientConnection реалізує обмін інформацією з конкретним клієнтом. В ньому зберігається об’єкт класу Socket, до якого приєднаний цей клієнт, та створюється потік, в якому здійснюється періодична спроба читати з сокета. Якщо ця спроба завершується успіхом, тобто надійшло повідомлення від клієнта, це повідомлення аналізується і здійснюється відповідна реакція. Для здіснення цієї реакції викликаються методи класу Server, об’єкт якого передається класу ClientConnection в якості параметра конструктора. Крім того в цьому класі є метод, який здійснює безпосереднє надсилання інформації до клієнта. Коли серверу потрібно надіслати інформацію конкретному клієнтові, він викликає цей метод.

клас Client:

import java.util.*;

import java.io.*;

import java.net.*;

import java.awt.*;

import java.applet.*;

public class Client extends Applet {

private ServerConnection server;

private String serverName;

private boolean single = false;

private boolean seen_pass = false;

private boolean name_set = false;

private String name;

private String others_name;

private Panel topPanel;

private Label prompt;

private TextField namefield;

private Button done;

private TextField chatfield;

private List idList;

private TextArea dialogArea;

public void init() {

setLayout( new BorderLayout() );

serverName = getCodeBase().getHost();

if (serverName.equals(""))

serverName = "localhost";

prompt = new Label("Enter id:");

namefield = new TextField(30);

topPanel = new Panel();

topPanel.setBackground(new Color(255, 255, 200));

topPanel.add(prompt);

topPanel.add(namefield);

add("North", topPanel);

idList = new List(10, false);

add("West", idList );

dialogArea = new TextArea();

dialogArea.setEditable( false );

add("Center", dialogArea );

}

public void start() {

try {

showStatus("Connecting to " + serverName);

server = new ServerConnection(this,serverName);

server.start();

showStatus("Connected: " + serverName);

} catch (Exception e) {

single = true;

}

}

public void stop() {

if (!single)

server.quit();

}

void add(String id, String hostname, String name) {

delete(id); // in case it is already there.

idList.addItem("(" + id + ") " + name + "@" + hostname);

}

void delete(String id) {

for (int i = 0; i < idList.countItems(); i++) {

String s = idList.getItem(i);

s = s.substring(s.indexOf("(") + 1, s.indexOf(")"));

if (s.equals(id)) {

idList.delItem(i);

break;

}

}

if (idList.countItems() == 0)

showStatus("Wait for other players to arrive.");

}

private String getName(String id) {

for (int i = 0; i < idList.countItems(); i++) {

String s = idList.getItem(i);

String id1 = s.substring(s.indexOf("(") + 1, s.indexOf(")"));

if (id1.equals(id)) {

return s.substring(s.indexOf(" ") + 3, s.indexOf("@"));

}

}

return null;

}

void chat(String id, String s) {

dialogArea.appendText(id + ": " + s+ "&bsol;n");//append

showStatus(id + ": " + s);

}

void quit(String id) {

showStatus(id + " just quit.");

delete(id);

}

private void nameEntered(String s) {

if (s.equals(""))

return;

System.out.println(s);