import java.io.*; // Импорт используемых пакетов 
import java.net.*;
import java.util.*; /**
*	Это приложение реализует протокол передачи информации об акциях,
*	выдавая эту информацию клиентам.
*	Sauthor David W. Baker
*	Автор Дэвид Бейкер
*	0version 1.1
* Версия 1.1
*/
public class StockQuoteServer {
// Порт, который будет прослушиваться сервером.
private static final int SERVER_PORT = 1701;
// Длина очереди входящих соединений.
private static final int MAX_CLIENTS = 50;
// Файл с данными в виде:
// <идентификатор акции> <информация об акции>
private static final File STOCK_QUOTES_FILE =
new File("stockquotes.txt");
private ServerSocket listenSocket = null;
private String[] stockInfo;
private Date stockInfoTime;
private long stockFileMod;
// Флаг, сброс которого приводит
// к завершению работы сервера.
private boolean keepRunning = true;
/**
* Запуск приложения.
* Эрагага args Ignored command line arguments.
* args - параметры командной строки - игнорируются
*/
public static void main(String[] args) { StockQuoteServer server = new StockQuoteServer(); server.serveQuotes();
} /**
* Конструктор загружает данные об акциях,
* после чего сервер ожидает
* запросов от клиентов.
*/
public StockQuoteServer() {
// Загружает данные и при ошибке завершает работу.
if (!loadQuotes()) System.exit(1);
try {
// Создать сокет.
listenSocket =
new ServerSocket(SERVER_PORT,MAX_CLIENTS);
} catch(IOException excpt) {
System.err.println("Onable to listen on port " +
// "Невозможно слушать порт ..."
SERVER_PORT + ": " + excpt);
System.exit(1);
}
} /**
* Загрузка данных из файла.
*/
protected boolean loadQuotes() {
String fileLine;
StringBuffer inputBuffer = new StringBuffer();
int numStocks = 0;
try {
// Создать поток для чтения файла данных.
DataInputStream stockInput = new DataInputStream(
new FileInputStream(STOCK_QUOTES_FILE));
// Считать каадую строку.
while   ((fileLine = stockInput.readLine())   != null)   {
// Поместить строку в буфер.
inputBuffer.append(fileLine + "\n");
numStocks++;   // увеличить счетчик.
}
stockInput.close();
// Сохранить время последней модификации.
stockFileMod = STOCK_QUOTES_FILE.lastModified();
} catch(FileNotFoundException excpt)   {
System.err.println("Unable to find file:   " + excpt);
// "Не найден файл"
return false;
} catch(IOException excpt)   {
System.err.println("Failed I/O:   " + excpt);
// "Ошибка ввода/вывода"
return false;
}
// Создать массив строк для чтения информации из файла.
stockInfo = new String[numStocks];
String inputString = inputBuffer.toString();
// Указатели для создания подстрок..
int stringStart = 0,   // начало строки
stringEnd = 0;   // конец строки
for   (int index = 0;   index < numStocks;   index ++)   { // Найти конец строки.
stringEnd = inputString.indexOf("\n",stringStart); // Если символ \n больше не встретился, 
// взять весь остаток inputString.
if  (stringEnd == -1) {
stockInfo[index]   = inputString.substring(stringStart); 
// иначе взять подстроку до символа \n 
}  else   
{
stockInfo[index]  =
inputString.substring(stringStart,stringEnd); }
// передвинуть указатель начала подстроки. 
stringStart = stringEnd + 1; }
stockInfoTime = new Date();   // сохранить время загрузки, 
return true;
}
/**
* Этот метод ожидает обращений от клиентов
*/
public void serveQuotes() {
Socket clientSocket = null;
try {
while(keepRunning) {
// Присоединить нового клиента.
clientSocket = listenSocket.accept();
// Если файл данных изменен,
// загрузить данные повторно.
if (stockFileMod != STOCK_QUOTES_FILE.lastModified()) {
loadQuotes();
}
// Создать новый обработчик.
StockQuoteHandler newHandler = new
StockQuoteHandler(clientSocket,stockInfo,
stockInfoTime);
Thread newHandlerThread = new Thread(newHandler);
newHandlerThread.start();
}
listenSocket.close();
} catch(IOException excpt) 
{
System.err.println("Failed I/O: "+ excpt);
// "Ошибка ввода/вывода"
}
}
/**
* Метод для остановки сервера.
*/
protected void stop() 
{
if (keepRunning) {
keepRunning = false;
}
}
} /**
* Класс для обеспечения связи
* с отдельным клиентом.
*/
class StockQuoteHandler implements Runnable 
{
private Socket mySocket = null;
private PrintStream clientSend = null;
private DataInputStream clientReceive = null;
private String[] stockInfo;
private Date stockInfoTime;
/**
* Конструктор инициализирует переменные экземпляра
* @param newSocket Socket to the incoming client.
* newSocket - сокет для связи с клиентом
* 8param info The stock data.
* info - данные об акциях
* 8param time The time when the data was loaded.
* time - время загрузки информации
*/
public StockQuoteHandler(Socket newSocket,
String[]   info,   Date time)   {
mySocket = newSocket;
stockInfo = info;
stockInfoTime = time;
} /**
* Поток, реализующий обмен данными
*/
public void run() 
{
String nextLine;
String quoteID;
String quoteResponse;
try {
clientSend =
new PrintStream(mySocket.getOutputStream());
clientReceive =
new DataInputStream(mySocket.getInputStream());
clientSend.println("+HELLO "+ stockInfoTime);
clientSend.flush() ;
// Получить строку от клиента и ответить
while((nextLine = clientReceive.readLine())
!= null) {
nextLine = nextLine.toUpperCase() ;
// команда QUIT.
if (nextLine.indexOf("QOIT") == 0) break;
// команда STOCK.
else if (nextLine.indexOf("STOCK: ") == 0) {
quoteID =
nextLine.substring("STOCK: ".length());
quoteResponse = getQuote(quoteID);
clientSend.println(quoteResponse) ;
clientSend.flush();
}
// неизвестная команда.
else {
clientSend.println("-ERR UNKNOWN COMMAND");
clientSend.flush();
}
}
clientSend.println("+BYE");
clientSend.flush();
} catch(IOException excpt) 
{
System.err.println("Failed I/O: " + excpt);
// "Ошибка ввода/вывода"
// Наконец, закрыть потоки и сокет.
} finally {
try {
if (clientSend != null) clientSend.close();
if (clientReceive != null) clientReceive.close();
if (mySocket != null) mySocket.close();
} catch(IOException excpt) 
{
System.err.println("Failed I/O: " + excpt);
// "Ошибка ввода/вывода"
}
}
}
/**
* Метод для нахождения информации
* по заданному идентификатору акции.
* Эрагат quoteID The stock ID to look up.
* quoteID - идентификатор акции
* Sreturn The releveant data.
* возвращаемое значение - данные по акции
*/
protected String getQuote(String quoteID) {
for(int index = 0; index < stockInfo.length; index++) {
// если найдено соответствие, возвратить данные.
if(stockInfo[index].indexOf(quoteID) == 0)
return "+" + stockInfo[index];
}
// в противном случае идентификатор неизвестен.
return "-ERR UNKNOWN STOCK ID";
}
}
Hosted by uCoz