diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..82969bc
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_thoughtworks_binding_binding_2_12_11_9_0_56_3af5a32a.xml b/.idea/libraries/Maven__com_thoughtworks_binding_binding_2_12_11_9_0_56_3af5a32a.xml
new file mode 100644
index 0000000..78df4ea
--- /dev/null
+++ b/.idea/libraries/Maven__com_thoughtworks_binding_binding_2_12_11_9_0_56_3af5a32a.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_thoughtworks_binding_fxml_2_12_11_9_0_56_3af5a32a.xml b/.idea/libraries/Maven__com_thoughtworks_binding_fxml_2_12_11_9_0_56_3af5a32a.xml
new file mode 100644
index 0000000..d926942
--- /dev/null
+++ b/.idea/libraries/Maven__com_thoughtworks_binding_fxml_2_12_11_9_0_56_3af5a32a.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_thoughtworks_binding_safebuffer_2_12_11_9_0_56_3af5a32a.xml b/.idea/libraries/Maven__com_thoughtworks_binding_safebuffer_2_12_11_9_0_56_3af5a32a.xml
new file mode 100644
index 0000000..3808b27
--- /dev/null
+++ b/.idea/libraries/Maven__com_thoughtworks_binding_safebuffer_2_12_11_9_0_56_3af5a32a.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_thoughtworks_binding_xmlextractor_2_12_11_9_0_56_3af5a32a.xml b/.idea/libraries/Maven__com_thoughtworks_binding_xmlextractor_2_12_11_9_0_56_3af5a32a.xml
new file mode 100644
index 0000000..a367764
--- /dev/null
+++ b/.idea/libraries/Maven__com_thoughtworks_binding_xmlextractor_2_12_11_9_0_56_3af5a32a.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_thoughtworks_enableIf_enableif_2_12_1_1_7.xml b/.idea/libraries/Maven__com_thoughtworks_enableIf_enableif_2_12_1_1_7.xml
new file mode 100644
index 0000000..a23baed
--- /dev/null
+++ b/.idea/libraries/Maven__com_thoughtworks_enableIf_enableif_2_12_1_1_7.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_thoughtworks_extractor_extractor_2_12_2_1_2.xml b/.idea/libraries/Maven__com_thoughtworks_extractor_extractor_2_12_2_1_2.xml
new file mode 100644
index 0000000..81e93f5
--- /dev/null
+++ b/.idea/libraries/Maven__com_thoughtworks_extractor_extractor_2_12_2_1_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_thoughtworks_q_q_2_12_1_0_4.xml b/.idea/libraries/Maven__com_thoughtworks_q_q_2_12_1_0_4.xml
new file mode 100644
index 0000000..6f2f6cc
--- /dev/null
+++ b/.idea/libraries/Maven__com_thoughtworks_q_q_2_12_1_0_4.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_thoughtworks_sde_core_2_12_3_3_2.xml b/.idea/libraries/Maven__com_thoughtworks_sde_core_2_12_3_3_2.xml
new file mode 100644
index 0000000..57dc649
--- /dev/null
+++ b/.idea/libraries/Maven__com_thoughtworks_sde_core_2_12_3_3_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_9.xml b/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_9.xml
new file mode 100644
index 0000000..9050e00
--- /dev/null
+++ b/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_9.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_openjfx_javafx_base_11.xml b/.idea/libraries/Maven__org_openjfx_javafx_base_11.xml
new file mode 100644
index 0000000..88eebdf
--- /dev/null
+++ b/.idea/libraries/Maven__org_openjfx_javafx_base_11.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_openjfx_javafx_base_mac_11.xml b/.idea/libraries/Maven__org_openjfx_javafx_base_mac_11.xml
new file mode 100644
index 0000000..f8b66bd
--- /dev/null
+++ b/.idea/libraries/Maven__org_openjfx_javafx_base_mac_11.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_openjfx_javafx_controls_11.xml b/.idea/libraries/Maven__org_openjfx_javafx_controls_11.xml
new file mode 100644
index 0000000..40e5c7e
--- /dev/null
+++ b/.idea/libraries/Maven__org_openjfx_javafx_controls_11.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_openjfx_javafx_controls_mac_11.xml b/.idea/libraries/Maven__org_openjfx_javafx_controls_mac_11.xml
new file mode 100644
index 0000000..a2793fc
--- /dev/null
+++ b/.idea/libraries/Maven__org_openjfx_javafx_controls_mac_11.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_openjfx_javafx_fxml_11.xml b/.idea/libraries/Maven__org_openjfx_javafx_fxml_11.xml
new file mode 100644
index 0000000..3eaa3ca
--- /dev/null
+++ b/.idea/libraries/Maven__org_openjfx_javafx_fxml_11.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_openjfx_javafx_fxml_mac_11.xml b/.idea/libraries/Maven__org_openjfx_javafx_fxml_mac_11.xml
new file mode 100644
index 0000000..e8a768e
--- /dev/null
+++ b/.idea/libraries/Maven__org_openjfx_javafx_fxml_mac_11.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_openjfx_javafx_graphics_11.xml b/.idea/libraries/Maven__org_openjfx_javafx_graphics_11.xml
new file mode 100644
index 0000000..adbd0c7
--- /dev/null
+++ b/.idea/libraries/Maven__org_openjfx_javafx_graphics_11.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_openjfx_javafx_graphics_mac_11.xml b/.idea/libraries/Maven__org_openjfx_javafx_graphics_mac_11.xml
new file mode 100644
index 0000000..b04140a
--- /dev/null
+++ b/.idea/libraries/Maven__org_openjfx_javafx_graphics_mac_11.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_scala_lang_scala_library_2_12_10.xml b/.idea/libraries/Maven__org_scala_lang_scala_library_2_12_10.xml
new file mode 100644
index 0000000..80b67f7
--- /dev/null
+++ b/.idea/libraries/Maven__org_scala_lang_scala_library_2_12_10.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_scala_lang_scala_reflect_2_12_10.xml b/.idea/libraries/Maven__org_scala_lang_scala_reflect_2_12_10.xml
new file mode 100644
index 0000000..ab4bd03
--- /dev/null
+++ b/.idea/libraries/Maven__org_scala_lang_scala_reflect_2_12_10.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_scalaz_scalaz_core_2_12_7_2_27.xml b/.idea/libraries/Maven__org_scalaz_scalaz_core_2_12_7_2_27.xml
new file mode 100644
index 0000000..04916b7
--- /dev/null
+++ b/.idea/libraries/Maven__org_scalaz_scalaz_core_2_12_7_2_27.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_scalaz_scalaz_effect_2_12_7_2_27.xml b/.idea/libraries/Maven__org_scalaz_scalaz_effect_2_12_7_2_27.xml
new file mode 100644
index 0000000..71bd09a
--- /dev/null
+++ b/.idea/libraries/Maven__org_scalaz_scalaz_effect_2_12_7_2_27.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_typelevel_macro_compat_2_12_1_1_1.xml b/.idea/libraries/Maven__org_typelevel_macro_compat_2_12_1_1_1.xml
new file mode 100644
index 0000000..6a3194c
--- /dev/null
+++ b/.idea/libraries/Maven__org_typelevel_macro_compat_2_12_1_1_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_xerial_sqlite_jdbc_3_36_0_3.xml b/.idea/libraries/Maven__org_xerial_sqlite_jdbc_3_36_0_3.xml
new file mode 100644
index 0000000..35d2f81
--- /dev/null
+++ b/.idea/libraries/Maven__org_xerial_sqlite_jdbc_3_36_0_3.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..2e289ef
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..3e9894b
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..e96534f
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..83bc6dc
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,266 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1646087030962
+
+
+ 1646087030962
+
+
+ 1646256709011
+
+
+
+ 1646256709011
+
+
+ 1646256984318
+
+
+
+ 1646256984318
+
+
+ 1646257098309
+
+
+
+ 1646257098309
+
+
+ 1646489511920
+
+
+
+ 1646489511920
+
+
+ 1646525502805
+
+
+
+ 1646525502805
+
+
+ 1646839660802
+
+
+
+ 1646839660802
+
+
+ 1647828285514
+
+
+
+ 1647828285515
+
+
+ 1648467015982
+
+
+
+ 1648467015982
+
+
+ 1648899327288
+
+
+
+ 1648899327288
+
+
+ 1649376819371
+
+
+
+ 1649376819371
+
+
+ 1649719077520
+
+
+
+ 1649719077520
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Chatty.iml b/Chatty.iml
new file mode 100644
index 0000000..f409c0e
--- /dev/null
+++ b/Chatty.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Client/Client.iml b/Client/Client.iml
new file mode 100644
index 0000000..03fe45e
--- /dev/null
+++ b/Client/Client.iml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Client/pom.xml b/Client/pom.xml
index a47135e..c7dfb9d 100644
--- a/Client/pom.xml
+++ b/Client/pom.xml
@@ -15,5 +15,44 @@
8
8
+
+
+
+
+ com.zenjava
+ javafx-maven-plugin
+ 2.0
+
+ Main
+
+
+
+
+
+
+ com.thoughtworks.binding
+ fxml_2.12
+ 11.9.0+56-3af5a32a
+
+
+ org.openjfx
+ javafx-fxml
+ 11
+
+
+ org.example
+ Command
+ 1.0-SNAPSHOT
+ compile
+
+
+ org.example
+ Server
+ 1.0-SNAPSHOT
+ compile
+
+
+
+
\ No newline at end of file
diff --git a/Client/src/main/java/Client.java b/Client/src/main/java/Client.java
deleted file mode 100644
index c64e2de..0000000
--- a/Client/src/main/java/Client.java
+++ /dev/null
@@ -1,57 +0,0 @@
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.Socket;
-import java.util.Scanner;
-
-public class Client {
- private static final int PORT = 8189;
- private static final String ADDRESS = "localhost";
-
- public static void main(String[] args) {
- Socket socket = null;
- Scanner scanner = new Scanner(System.in);
- try{
- socket = new Socket(ADDRESS,PORT);
- System.out.println("Connected to server:" + socket.getRemoteSocketAddress());
- DataInputStream in = new DataInputStream(socket.getInputStream());
- DataOutputStream out = new DataOutputStream(socket.getOutputStream());
-
-
- Thread thread = new Thread(()->{
- while(true) {
- try {
- out.writeUTF(scanner.nextLine());
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- });
- thread.setDaemon(true);
- thread.start();
-
- while(true){
- String str = in.readUTF();
- if(str.equals("/end")){
- System.out.println("lost connection to the server...");
- out.writeUTF("/end");
- break;
-
- }else{
- System.out.println("Server : " + str);
- }
- }
-
- } catch (IOException e) {
- e.printStackTrace();
- }finally {
- try {
- socket.close();
- } catch (IOException | NullPointerException e) {
- e.printStackTrace();
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/Client/src/main/java/Controller.java b/Client/src/main/java/Controller.java
new file mode 100644
index 0000000..02d012f
--- /dev/null
+++ b/Client/src/main/java/Controller.java
@@ -0,0 +1,249 @@
+import constants.Command;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.fxml.Initializable;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.scene.control.ListView;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.HBox;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.Socket;
+import java.net.URL;
+import java.util.ResourceBundle;
+
+public class Controller implements Initializable {
+ @FXML
+ public TextField textField;
+ @FXML
+ public TextArea textArea;
+ @FXML
+ public TextField loginField;
+ @FXML
+ public PasswordField passwordField;
+ @FXML
+ public HBox authPanel;
+ @FXML
+ public HBox msgPanel;
+ @FXML
+ public ListView clientList;
+
+ private Socket socket;
+ private static final int PORT = 8189;
+ private static final String ADDRESS ="localhost";
+
+ private DataInputStream in;
+ private DataOutputStream out;
+
+ private boolean authenticated;
+ private String nickname;
+ private Stage stage;
+ private Stage regStage;
+ private RegController regController;
+ private String login;
+
+ public void setAuthenticated(boolean authenticated) {
+ this.authenticated = authenticated;
+ authPanel.setVisible(!authenticated);
+ authPanel.setManaged(!authenticated);
+ msgPanel.setVisible(authenticated);
+ msgPanel.setManaged(authenticated);
+ clientList.setVisible(authenticated);
+ clientList.setManaged(authenticated);
+
+ if (!authenticated){
+ nickname = "";
+ History.stop();
+ }
+
+ textArea.clear();
+ setTitle(nickname);
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ Platform.runLater(() -> {
+ stage = (Stage) textField.getScene().getWindow();
+ stage.setOnCloseRequest(event -> {
+ System.out.println("bye");
+ if (socket != null && !socket.isClosed()) {
+ try {
+ out.writeUTF(Command.END);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ });
+ setAuthenticated(false);
+ }
+
+ private void connect() {
+ try {
+ socket = new Socket(ADDRESS, PORT);
+ in = new DataInputStream(socket.getInputStream());
+ out = new DataOutputStream(socket.getOutputStream());
+
+ new Thread(() -> {
+ try {
+ //цикл аутентификации
+ while (true) {
+ String str = in.readUTF();
+
+ if (str.startsWith("/")) {
+ if (str.equals(Command.END)) {
+ break;
+ }
+ if (str.startsWith(Command.AUTH_OK)) {
+ nickname = str.split(" ")[1];
+ setAuthenticated(true);
+ textArea.appendText(History.getLastHundredLinesOfHistory(login));
+ History.start(login);
+ break;
+ }
+ if (str.equals(Command.REG_OK)||str.equals(Command.REG_NO)){
+ regController.result(str);
+ }
+ } else {
+ textArea.appendText(str + "\n");
+ }
+ }
+ //цикл работы
+ while (authenticated) {
+ String str = in.readUTF();
+
+ if (str.startsWith("/")) {
+ if (str.equals(Command.END)) {
+ break;
+ }
+ if (str.startsWith(Command.CLIENTLIST)) {
+ String[] token = str.split(" ");
+
+ Platform.runLater(()->{
+ clientList.getItems().clear();
+ for (int i=1;i {
+ stage.setTitle(title);
+ });
+ }
+
+ public void clientListMouseAction(MouseEvent mouseEvent) {
+ System.out.println(clientList.getSelectionModel().getSelectedItems());
+ String receiver = clientList.getSelectionModel().getSelectedItem();
+ textField.setText(String.format("/w %s",receiver));
+ }
+
+ private void createRegStage(){
+ try {
+ FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("reg.fxml"));
+ Parent root = fxmlLoader.load();
+
+ regStage = new Stage();
+ regStage.setTitle("Chatty registration");
+ regStage.setScene(new Scene(root, 600, 500));
+
+ regController = fxmlLoader.getController();
+ regController.setController(this);
+
+ regStage.initStyle(StageStyle.UTILITY);
+ regStage.initModality(Modality.APPLICATION_MODAL);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void tryToReg(ActionEvent actionEvent) {
+ if (regStage == null){
+ createRegStage();
+ }
+ regStage.show();
+ }
+
+ public void registration(String login, String password, String nickname){
+ String msg = String.format("/reg %s %s %s",login, password, nickname);
+
+ if (socket == null|| socket.isClosed()){
+ connect();
+ }
+
+ try {
+ out.writeUTF(msg);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/Client/src/main/java/History.java b/Client/src/main/java/History.java
new file mode 100644
index 0000000..563460b
--- /dev/null
+++ b/Client/src/main/java/History.java
@@ -0,0 +1,54 @@
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+
+public class History {
+
+ private static PrintWriter out;
+
+ private static String getHistoryFilenameByLogin(String login){
+ return "history/history_" + login +".txt";
+ }
+
+ public static void start(String login){
+ try {
+ out = new PrintWriter(new FileOutputStream(getHistoryFilenameByLogin(login),true),true);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void stop(){
+ if (out!=null){
+ out.close();
+ }
+ }
+
+ public static void writeLine(String msg){
+ out.println(msg);
+ }
+
+ public static String getLastHundredLinesOfHistory(String login){
+ if (!Files.exists(Paths.get(getHistoryFilenameByLogin(login)))){
+ return "";
+ }
+ StringBuilder stringBuilder = new StringBuilder();
+ try {
+
+ List historyLines = Files.readAllLines(Paths.get(getHistoryFilenameByLogin(login)));
+ int startpos = 0;
+ if (historyLines.size()>100){
+ startpos = historyLines.size()-100;
+ }
+ for (int i = startpos;i
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Client/src/main/resources/sample.fxml b/Client/src/main/resources/sample.fxml
new file mode 100644
index 0000000..1ea8273
--- /dev/null
+++ b/Client/src/main/resources/sample.fxml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Client/target/classes/Client.class b/Client/target/classes/Client.class
deleted file mode 100644
index 8289486..0000000
Binary files a/Client/target/classes/Client.class and /dev/null differ
diff --git a/Command/Command.iml b/Command/Command.iml
new file mode 100644
index 0000000..08c1eba
--- /dev/null
+++ b/Command/Command.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Command/pom.xml b/Command/pom.xml
new file mode 100644
index 0000000..ca97141
--- /dev/null
+++ b/Command/pom.xml
@@ -0,0 +1,19 @@
+
+
+
+ Chatty
+ org.example
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ Command
+
+
+ 11
+ 11
+
+
+
\ No newline at end of file
diff --git a/Command/src/main/java/constants/Command.java b/Command/src/main/java/constants/Command.java
new file mode 100644
index 0000000..9a29570
--- /dev/null
+++ b/Command/src/main/java/constants/Command.java
@@ -0,0 +1,17 @@
+package constants;
+
+public class Command {
+ public static final String END = "/end" ;
+ public static final String AUTH = "/auth" ;
+ public static final String AUTH_OK = "/auth_OK" ;
+ public static final String REG = "/reg" ;
+ public static final String REG_OK = "/reg_ok" ;
+ public static final String REG_NO = "/reg_no" ;
+ public static final String CLIENTLIST = "/clientlist" ;
+ public static final String W = "/w" ;
+ public static final String YOURNICKIS = "/yournickis " ;
+ public static final String CHANGENICK = "/changeNick";
+
+
+
+}
diff --git a/Server/Server.iml b/Server/Server.iml
new file mode 100644
index 0000000..30622b4
--- /dev/null
+++ b/Server/Server.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Server/pom.xml b/Server/pom.xml
index 99c3db8..2b1c8a2 100644
--- a/Server/pom.xml
+++ b/Server/pom.xml
@@ -10,6 +10,22 @@
4.0.0
Server
+
+
+ org.example
+ Command
+ 1.0-SNAPSHOT
+ compile
+
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.36.0.3
+
+
+
+
8
diff --git a/Server/src/main/java/AuthService.java b/Server/src/main/java/AuthService.java
new file mode 100644
index 0000000..0fe9193
--- /dev/null
+++ b/Server/src/main/java/AuthService.java
@@ -0,0 +1,8 @@
+public interface AuthService {
+
+ String getNicknameByLoginAndPassword(String login, String password);
+
+ boolean registration(String login, String password, String nickname);
+
+ boolean changeNickname(String currentNick, String newNick);
+}
diff --git a/Server/src/main/java/ClientHandler.java b/Server/src/main/java/ClientHandler.java
new file mode 100644
index 0000000..e6617d2
--- /dev/null
+++ b/Server/src/main/java/ClientHandler.java
@@ -0,0 +1,167 @@
+import constants.Command;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.logging.Logger;
+
+public class ClientHandler {
+
+ private static final Logger logger = Logger.getLogger(ClientHandler.class.getName());
+ private Server server;
+ private Socket socket;
+ private DataInputStream in;
+ private DataOutputStream out;
+
+ private boolean authenticated;
+ private String nickname;
+
+ public String getLogin() {
+ return login;
+ }
+
+ private String login;
+
+ public ClientHandler(Server server, Socket socket) {
+ try {
+ this.server = server;
+ this.socket = socket;
+
+ in = new DataInputStream(socket.getInputStream());
+ out = new DataOutputStream(socket.getOutputStream());
+
+ server.getExecutorService().execute(() -> {
+ try {
+ socket.setSoTimeout(5000);
+ //цикл аутентификации
+ while (true) {
+ String str = in.readUTF();
+
+ if (str.startsWith("/")) {
+ if (str.equals(Command.END)) {
+ sendMsg(Command.END);
+ break;
+ }
+
+ if (str.startsWith(Command.AUTH)) {
+ String[] token = str.split(" ", 3);
+ if (token.length < 3) {
+ continue;
+ }
+ String newNick = server.getAuthService()
+ .getNicknameByLoginAndPassword(token[1], token[2]);
+ login = token[1];
+ if (newNick != null) {
+ if (!server.isLoginAuthenticated(login)){
+ nickname = newNick;
+ sendMsg(Command.AUTH_OK + " "+ nickname);
+ authenticated = true;
+ server.subscribe(this);
+ logger.info("Client " + nickname+ " authenticated");
+ break;
+ }
+ if (str.equals(Command.REG_OK)|| str.equals(Command.REG_NO)){
+
+ }
+ else{
+ sendMsg("Уже произведен вход с данной учетной записью");
+ }
+
+ } else {
+ sendMsg("Логин / пароль не верны");
+ }
+ }
+ if (str.startsWith(Command.REG)) {
+ String[] token = str.split(" ");
+ if (token.length < 4) {
+ continue;
+ }
+ if(server.getAuthService().registration(token[1],token[2],token[3])){
+ sendMsg(Command.REG_OK);
+ }else{
+ sendMsg(Command.REG_NO);
+ }
+ }
+ }
+ }
+ //цикл работы
+ while (authenticated) {
+ socket.setSoTimeout(0);
+ String str = in.readUTF();
+
+ if (str.startsWith("/")) {
+ if (str.equals(Command.END)) {
+ sendMsg(Command.END);
+ break;
+ }
+ if (str.startsWith(Command.W)) {
+ String[] token = str.split(" ", 3);
+ if (token.length < 3) {
+ continue;
+ }
+ server.privateMsg(this,token[1],token[2]);
+ }
+
+ if (str.startsWith(Command.CHANGENICK)){
+ String[] token = str.split("\\s+",2);
+ if (token.length<2){
+ continue;
+ }
+ if (token[1].contains(" ")){
+ sendMsg("nick doesn't contain space simbols");
+ continue;
+ }
+ if (server.getAuthService().changeNickname(this.nickname,token[1])){
+ sendMsg("/yournickis " + token[1]);
+ sendMsg("your nick updated to " + token[1]);
+ this.nickname = token[1];
+ server.broadcastClientList();
+ }else{
+ sendMsg("can't update nick. This nick is busy");
+ }
+ }
+
+ }else {
+ server.broadcastMsg(this, str);
+ }
+
+
+
+ }
+ }catch (SocketTimeoutException e){
+ sendMsg(Command.END);
+ e.printStackTrace();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ server.unsubscribe(this);
+ System.out.println("Client disconnected");
+ try {
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ });
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void sendMsg(String msg) {
+ try {
+ out.writeUTF(msg);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public String getNickname() {
+ return nickname;
+ }
+}
diff --git a/Server/src/main/java/DBAuthService.java b/Server/src/main/java/DBAuthService.java
new file mode 100644
index 0000000..d2f0ce8
--- /dev/null
+++ b/Server/src/main/java/DBAuthService.java
@@ -0,0 +1,17 @@
+public class DBAuthService implements AuthService {
+
+ @Override
+ public String getNicknameByLoginAndPassword(String login, String password) {
+ return SQLHandler.getNicknameByLoginAndPassword(login,password);
+ }
+
+ @Override
+ public boolean registration(String login, String password, String nickname) {
+ return SQLHandler.registration(login,password,nickname);
+ }
+
+ @Override
+ public boolean changeNickname(String currentNick, String newNick) {
+ return SQLHandler.changeNickname(newNick,currentNick);
+ }
+}
diff --git a/Server/src/main/java/SQLHandler.java b/Server/src/main/java/SQLHandler.java
new file mode 100644
index 0000000..fc3d714
--- /dev/null
+++ b/Server/src/main/java/SQLHandler.java
@@ -0,0 +1,83 @@
+import java.sql.*;
+
+public class SQLHandler {
+
+ private static Connection connection;
+ private static PreparedStatement psGetNickByLoginAndPass;
+ private static PreparedStatement psChangeNick;
+ private static PreparedStatement psReg;
+
+ public static String getNicknameByLoginAndPassword(String login, String password) {
+ String nickname = null;
+ try {
+ psGetNickByLoginAndPass.setString(1, login);
+ psGetNickByLoginAndPass.setString(2, password);
+ ResultSet resultSet = psGetNickByLoginAndPass.executeQuery();
+ if (resultSet.next())
+ nickname = resultSet.getString("nickname");
+ resultSet.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return nickname;
+ }
+
+ public static boolean changeNickname(String newNick,String currentNick){
+ try {
+ psChangeNick.setString(1,newNick);
+ psChangeNick.setString(2,currentNick);
+ psChangeNick.executeUpdate();
+ return true;
+ } catch (SQLException throwables) {
+ throwables.printStackTrace();
+ return false;
+ }
+ }
+
+ public static boolean registration(String login, String password, String nickname) {
+ try {
+ psReg.setString(1,login);
+ psReg.setString(2,password);
+ psReg.setString(3,nickname);
+ psReg.executeUpdate();
+ return true;
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public static boolean connect(){
+ try {
+ Class.forName("org.sqlite.JDBC");
+ connection = DriverManager.getConnection("jdbc:sqlite:chattybase.db");
+ preparedALlStatements();
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ }
+
+ public static void disconnect(){
+ try {
+ psGetNickByLoginAndPass.close();
+ psChangeNick.close();
+ psReg.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void preparedALlStatements() throws Exception {
+ psGetNickByLoginAndPass = connection.prepareStatement("SELECT * FROM 'users' WHERE login = ? AND password = ?");
+ psChangeNick = connection.prepareStatement("UPDATE 'users' SET nickname = ? WHERE nickname = ?");
+ psReg = connection.prepareStatement("INSERT INTO users (login,password,nickname) VALUES (?,?,?)");
+ }
+}
diff --git a/Server/src/main/java/Server.java b/Server/src/main/java/Server.java
index 60e0f55..707f17c 100644
--- a/Server/src/main/java/Server.java
+++ b/Server/src/main/java/Server.java
@@ -1,53 +1,125 @@
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
-import java.util.Scanner;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
public class Server {
+ private static final Logger logger = Logger.getLogger(Server.class.getName());
+ private static ServerSocket server;
+ private static Socket socket;
+ private final int PORT= 8189;
- public static void main(String[] args) {
- Socket socket = null;
- Scanner scanner = new Scanner(System.in);
- try(ServerSocket serverSocket = new ServerSocket(8189)){
- System.out.println("server running...");
- socket = serverSocket.accept();
- System.out.println("Client connected");
- DataInputStream in = new DataInputStream(socket.getInputStream());
- DataOutputStream out = new DataOutputStream(socket.getOutputStream());
-
- Thread thread = new Thread(()->{
- while (true){
- try {
- out.writeUTF(scanner.nextLine());
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ private List clients;
+ private AuthService authService;
+
+ public ExecutorService getExecutorService() {
+ return executorService;
+ }
- });
+ private ExecutorService executorService;
- thread.setDaemon(true);
- thread.start();
+ public Server() {
+ executorService = Executors.newCachedThreadPool();
+ clients = new CopyOnWriteArrayList<>();
+
+ if (!SQLHandler.connect()){
+ throw new RuntimeException("access to database aborted");
+ }
+ authService = new DBAuthService();
+ try {
+ server = new ServerSocket(PORT);
+ logger.info("server started");
while(true){
- String str = in.readUTF();
- if (str.equals("/end")){
- System.out.println("client disconnected");
- out.writeUTF("/end");
- break;
- }else{
- System.out.println("Client: " +str);
- }
+ socket = server.accept();
+ logger.info("Client connected");
+ new ClientHandler(this,socket);
}
} catch (IOException e) {
e.printStackTrace();
+ logger.log(Level.SEVERE,e.getMessage(),e);
}finally {
+ executorService.shutdown();
+ SQLHandler.disconnect();
try {
socket.close();
- } catch (IOException | NullPointerException e) {
- e.printStackTrace();
+ } catch (IOException e) {
+ logger.log(Level.SEVERE,e.getMessage(),e);
+ }
+ try {
+ server.close();
+ } catch (IOException e) {
+ logger.log(Level.SEVERE,e.getMessage(),e);
+ }
+ }
+ }
+
+ public void broadcastMsg(ClientHandler sender, String msg){
+ String message = String.format("[ %s ]: %s", sender.getNickname(), msg);
+
+ for (ClientHandler client : clients) {
+ client.sendMsg(message);
+ }
+ }
+
+ public void privateMsg(ClientHandler sender,String recipient, String msg){
+ String message = String.format("from [ %s ] to [ %s ]: %s", sender.getNickname(),recipient, msg);
+
+ for (ClientHandler client : clients) {
+ if (client.getNickname().equals(recipient)){
+ client.sendMsg(message);
+ if (!sender.getNickname().equals(recipient)) {
+ sender.sendMsg(message);
+ }
+ return;
}
+
+ }
+
+ sender.sendMsg("user not found:" + recipient);
+ }
+
+ public boolean isLoginAuthenticated(String login){
+ for (ClientHandler client : clients) {
+ if (client.getLogin().equals(login)){
+ return true;
+ }
+ }return false;
+ }
+
+ public void broadcastClientList(){
+ StringBuilder sb = new StringBuilder("/clientlist");
+
+ for (ClientHandler c : clients) {
+ sb.append(" ").append(c.getNickname());
}
+
+ String msg = sb.toString();
+
+ for (ClientHandler c : clients) {
+ c.sendMsg(msg);
+ }
+ }
+
+ public void subscribe(ClientHandler clientHandler){
+ clients.add(clientHandler);
+ broadcastClientList();
+ }
+
+ public void unsubscribe(ClientHandler clientHandler){
+ clients.remove(clientHandler);
+ broadcastClientList();
+ }
+ public AuthService getAuthService() {
+ return authService;
+
}
}
diff --git a/Server/src/main/java/SimpleAuthService.java b/Server/src/main/java/SimpleAuthService.java
new file mode 100644
index 0000000..8544a47
--- /dev/null
+++ b/Server/src/main/java/SimpleAuthService.java
@@ -0,0 +1,58 @@
+import java.util.ArrayList;
+import java.util.List;
+
+public class SimpleAuthService implements AuthService{
+
+ private class UserData{
+ String login;
+ String password;
+ String nickname;
+
+ UserData(String login,String password,String nickname){
+ this.login = login;
+ this.password = password;
+ this.nickname = nickname;
+ }
+ }
+
+ private List users;
+
+ SimpleAuthService(){
+ users = new ArrayList<>();
+ users.add(new UserData("qwerty","qwerty","qwerty"));
+ users.add(new UserData("nick","qwerty","nick"));
+ users.add(new UserData("userPro","qwerty","user1"));
+
+ for (int i = 0; i < 9; i++) {
+ users.add(new UserData("user" + i, "pass" + i, "nick" + i));
+ }
+ }
+
+ @Override
+ public String getNicknameByLoginAndPassword(String login, String password) {
+ for (UserData user : users) {
+ if (user.login.equals(login)&& user.password.equals(password)){
+ return user.nickname;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean registration(String login, String password, String nickname) {
+ for (UserData user : users) {
+ if (user.login.equals(login)&& user.nickname.equals(nickname)){
+ return false;
+ }
+ }
+ users.add(new UserData(login,password,nickname));
+ return true;
+ }
+
+ @Override
+ public boolean changeNickname(String currentNick, String newNick) {
+ return false;
+ }
+
+
+}
diff --git a/Server/src/main/java/StartServer.java b/Server/src/main/java/StartServer.java
new file mode 100644
index 0000000..e632325
--- /dev/null
+++ b/Server/src/main/java/StartServer.java
@@ -0,0 +1,20 @@
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.logging.LogManager;
+
+public class StartServer {
+ public static void main(String[] args){
+ try{
+ LogManager logManager = LogManager.getLogManager();
+ logManager.readConfiguration(new FileInputStream("logging.properties"));
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ new Server();
+ }
+}
diff --git a/Server/target/classes/Server.class b/Server/target/classes/Server.class
index 1f0acd7..6c983c2 100644
Binary files a/Server/target/classes/Server.class and b/Server/target/classes/Server.class differ
diff --git a/logging.properties b/logging.properties
new file mode 100644
index 0000000..d0366b2
--- /dev/null
+++ b/logging.properties
@@ -0,0 +1,64 @@
+############################################################
+# Default Logging Configuration File
+#
+# You can use a different file by specifying a filename
+# with the java.util.logging.config.file system property.
+# For example java -Djava.util.logging.config.file=myfile
+############################################################
+
+############################################################
+# Global properties
+############################################################
+
+# "handlers" specifies a comma separated list of log Handler
+# classes. These handlers will be installed during VM startup.
+# Note that these classes must be on the system classpath.
+# By default we only configure a ConsoleHandler, which will only
+# show messages at the INFO and above levels.
+#handlers= java.util.logging.ConsoleHandler
+
+# To also add the FileHandler, use the following line instead.
+handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
+
+# Default global logging level.
+# This specifies which kinds of events are logged across
+# all loggers. For any given facility this global level
+# can be overriden by a facility specific level
+# Note that the ConsoleHandler also has a separate level
+# setting to limit messages printed to the console.
+.level= INFO
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = log_%g.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 10
+# Default number of locks FileHandler can obtain synchronously.
+# This specifies maximum number of attempts to obtain lock file by FileHandler
+# implemented by incrementing the unique field %u as per FileHandler API documentation.
+java.util.logging.FileHandler.maxLocks = 100
+java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.FileHandler.append = true
+
+# Limit the message that are printed on the console to INFO and above.
+java.util.logging.ConsoleHandler.level = INFO
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# Example to customize the SimpleFormatter output format
+# to print one-line log message like this:
+# : []
+#
+# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
+
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+
+# For example, set the com.xyz.foo logger to only log SEVERE
+# messages:
+# com.xyz.foo.level = SEVERE
diff --git a/pom.xml b/pom.xml
index 9f9118e..99f5699 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,11 +11,11 @@
Client
Server
+ Command
8
8
-
\ No newline at end of file