Browse Source

ready

master
esoe 2 years ago
commit
7a137e2797
  1. 75
      pom.xml
  2. 177
      src/main/java/ru/molokoin/Server.java
  3. 20
      src/test/java/ru/molokoin/AppTest.java

75
pom.xml

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.molokoin</groupId>
<artifactId>chat-server</artifactId>
<version>0.1</version>
<name>chat-server</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

177
src/main/java/ru/molokoin/Server.java

@ -0,0 +1,177 @@
package ru.molokoin;
import java.io.*;
import java.net.*;
import java.util.LinkedList;
/**
* проект реализует консольный многопользовательский чат.
* вход в программу запуска сервера - в классе Server.
* @author izotopraspadov, the tech
* @version 2.0
*/
class ServerSomthing extends Thread {
private Socket socket; // сокет, через который сервер общается с клиентом,
// кроме него - клиент и сервер никак не связаны
private BufferedReader in; // поток чтения из сокета
private BufferedWriter out; // поток завписи в сокет
/**
* для общения с клиентом необходим сокет (адресные данные)
* @param socket
* @throws IOException
*/
public ServerSomthing(Socket socket) throws IOException {
this.socket = socket;
// если потоку ввода/вывода приведут к генерированию искдючения, оно проброситься дальше
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
Server.story.printStory(out); // поток вывода передаётся для передачи истории последних 10
// сооюбщений новому поключению
start(); // вызываем run()
}
@Override
public void run() {
String word;
try {
// первое сообщение отправленное сюда - это никнейм
word = in.readLine();
try {
out.write(word + "\n");
out.flush(); // flush() нужен для выталкивания оставшихся данных
// если такие есть, и очистки потока для дьнейших нужд
} catch (IOException ignored) {}
try {
while (true) {
word = in.readLine();
if(word.equals("stop")) {
this.downService(); // харакири
break; // если пришла пустая строка - выходим из цикла прослушки
}
System.out.println("Echoing: " + word);
Server.story.addStoryEl(word);
for (ServerSomthing vr : Server.serverList) {
vr.send(word); // отослать принятое сообщение с привязанного клиента всем остальным влючая его
}
}
} catch (NullPointerException ignored) {}
} catch (IOException e) {
this.downService();
}
}
/**
* отсылка одного сообщения клиенту по указанному потоку
* @param msg
*/
private void send(String msg) {
try {
out.write(msg + "\n");
out.flush();
} catch (IOException ignored) {}
}
/**
* закрытие сервера
* прерывание себя как нити и удаление из списка нитей
*/
private void downService() {
try {
if(!socket.isClosed()) {
socket.close();
in.close();
out.close();
for (ServerSomthing vr : Server.serverList) {
if(vr.equals(this)) vr.interrupt();
Server.serverList.remove(this);
}
}
} catch (IOException ignored) {}
}
}
/**
* класс хранящий в ссылочном приватном
* списке информацию о последних 10 (или меньше) сообщениях
*/
class Story {
private LinkedList<String> story = new LinkedList<>();
/**
* добавить новый элемент в список
* @param el
*/
public void addStoryEl(String el) {
// если сообщений больше 10, удаляем первое и добавляем новое
// иначе просто добавить
if (story.size() >= 10) {
story.removeFirst();
story.add(el);
} else {
story.add(el);
}
}
/**
* отсылаем последовательно каждое сообщение из списка
* в поток вывода данному клиенту (новому подключению)
* @param writer
*/
public void printStory(BufferedWriter writer) {
if(story.size() > 0) {
try {
writer.write("History messages" + "\n");
for (String vr : story) {
writer.write(vr + "\n");
}
writer.write("/...." + "\n");
writer.flush();
} catch (IOException ignored) {}
}
}
}
public class Server {
public static final int PORT = 8080;
public static LinkedList<ServerSomthing> serverList = new LinkedList<>(); // список всех нитей - экземпляров
// сервера, слушающих каждый своего клиента
public static Story story; // история переписки
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(PORT);
story = new Story();
System.out.println("Server Started");
try {
while (true) {
// Блокируется до возникновения нового соединения:
Socket socket = server.accept();
try {
serverList.add(new ServerSomthing(socket)); // добавить новое соединенние в список
} catch (IOException e) {
// Если завершится неудачей, закрывается сокет,
// в противном случае, нить закроет его:
socket.close();
}
}
} finally {
server.close();
}
}
}

20
src/test/java/ru/molokoin/AppTest.java

@ -0,0 +1,20 @@
package ru.molokoin;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
}
Loading…
Cancel
Save