├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── LICENSE
├── README.md
├── checkstyle.xml
├── lesson-1
├── HOMEWORK.md
├── PITCHME.md
├── dir
│ ├── 2.txt
│ ├── channel_example_4.txt
│ ├── from.txt
│ ├── from_input.txt
│ ├── out.txt
│ ├── subdir0
│ │ └── file.txt
│ └── to.txt
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── ru
│ │ └── daniilazarnov
│ │ └── Main.java
│ └── test
│ ├── java
│ └── ru
│ │ └── daniilazarnov
│ │ ├── FilesExamplesTest.java
│ │ └── PathExamplesTest.java
│ └── resources
│ └── file.txt
├── lesson-2
├── pom.xml
├── slides
│ ├── PRESENTATION.md
│ └── img
│ │ ├── img.png
│ │ ├── img_1.png
│ │ ├── img_2.png
│ │ ├── img_3.png
│ │ ├── img_4.png
│ │ ├── img_5.png
│ │ ├── img_6.png
│ │ ├── img_7.png
│ │ └── img_8.png
└── src
│ ├── main
│ └── java
│ │ └── ru
│ │ └── daniilazarnov
│ │ └── NioChatServerExample.java
│ └── test
│ └── java
│ └── ru
│ └── daniilazarnov
│ └── BufferExamplesTest.java
├── lesson-3
├── pom.xml
├── slides
│ └── PRESENTATION.md
└── src
│ └── main
│ ├── java
│ └── ru
│ │ └── daniilazarnov
│ │ ├── auth
│ │ ├── AuthClient.java
│ │ ├── AuthHandler.java
│ │ ├── AuthServer.java
│ │ └── MainHandler.java
│ │ ├── hello
│ │ ├── HelloServer.java
│ │ ├── HelloServerHandler.java
│ │ └── IoClient.java
│ │ ├── pipeline
│ │ ├── MyClient.java
│ │ ├── MyServer.java
│ │ └── handlers
│ │ │ ├── in
│ │ │ ├── FinalInboundHandler.java
│ │ │ ├── FirstInboundHandler.java
│ │ │ ├── GatewayInboundHandler.java
│ │ │ └── SecondInboundHandler.java
│ │ │ └── out
│ │ │ ├── StringToByteBufOutboundHandler.java
│ │ │ └── StringToStringOutboundHandler.java
│ │ ├── proto
│ │ ├── client
│ │ │ ├── Network.java
│ │ │ └── ProtoClient.java
│ │ ├── old
│ │ │ ├── Network.java
│ │ │ ├── ProtoClient.java
│ │ │ └── ProtoFileSender.java
│ │ └── server
│ │ │ ├── ProtoHandler.java
│ │ │ ├── ProtoServer.java
│ │ │ └── State.java
│ │ └── serialization
│ │ ├── Client.java
│ │ ├── CloudServer.java
│ │ ├── CloudServerHandler.java
│ │ └── domain
│ │ ├── FileMessage.java
│ │ └── MyMessage.java
│ └── resources
│ └── Netty_Idea_Diagram.png
├── lesson-4
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── ru
│ │ └── daniilazarnov
│ │ └── Main.java
│ └── test
│ └── java
│ └── ru
│ └── daniilazarnov
│ ├── LambdaTest.java
│ └── StreamTest.java
├── lesson-6
├── pom.xml
├── slides
│ └── PRESENTATION.md
└── src
│ ├── main
│ └── java
│ │ └── ru
│ │ └── daniilazarnov
│ │ └── Main.java
│ └── test
│ └── java
│ └── ru
│ └── daniilazarnov
│ └── MainTest.java
├── lesson-7
├── pom.xml
├── slides
│ ├── PRESENTATION.md
│ └── images
│ │ ├── java_classloader_hierarchy.png
│ │ └── jvm_architecture.png
└── src
│ ├── main
│ └── java
│ │ └── ru
│ │ └── daniilazarnov
│ │ └── Main.java
│ └── test
│ └── java
│ └── ru
│ └── daniilazarnov
│ └── MainTest.java
├── pom.xml
└── project
├── README.md
├── TOR.md
├── client
├── pom.xml
└── src
│ └── main
│ └── java
│ └── ru
│ └── daniilazarnov
│ └── Client.java
├── common
├── pom.xml
└── src
│ └── main
│ └── java
│ └── ru
│ └── daniilazarnov
│ └── Common.java
├── pom.xml
├── project.drawio
└── server
├── pom.xml
└── src
└── main
└── java
└── ru
└── daniilazarnov
└── Server.java
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3 |
4 | name: Java CI with Maven
5 |
6 | on:
7 | push:
8 | branches: [ main ]
9 | pull_request:
10 | branches: [ main ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ${{ matrix.os }}
16 | strategy:
17 | matrix:
18 | os: [ ubuntu-latest, windows-latest ]
19 | java: [ 11 ]
20 |
21 | steps:
22 | - uses: actions/checkout@v2
23 | - name: Set up JDK
24 | uses: actions/setup-java@v1
25 | with:
26 | java-version: ${{ matrix.java }}
27 | - name: Checkstyle
28 | run: mvn validate
29 | - name: Build with Maven
30 | run: mvn -B package --file pom.xml
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
3 |
4 | **/target
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Daniil Azarnov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # java-net-course
2 |
--------------------------------------------------------------------------------
/checkstyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
33 |
34 |
35 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
--------------------------------------------------------------------------------
/lesson-1/HOMEWORK.md:
--------------------------------------------------------------------------------
1 | # Домашняя работа
2 |
3 | ---
4 |
5 | ### Задание:
6 |
7 | 1. Подписаться на репозиторий https://github.com/azarnovdaniil/java-net-course
8 | 2. Поставить звездочку
9 | 3. Сделать fork репозитория
10 | 4. Прислать pull-request в репозиторий курса с заполненным блоком ответы.
11 | 5. Прислать ссылку на pull-request через платформу.
12 |
13 | ---
14 |
15 | ### Вопросы:
16 |
17 | 1. Как организовать клиент-серверное взаимодействие?
18 | 2. Как и в каком виде передавать файлы?
19 | 3. Как пересылать большие файлы?
20 | 4. Как пересылать служебные команды?
21 | 5. Как передавать структуру каталогов/файлов?
22 | 6. Какую библиотеку использовать для сетевого взаимодействия: java.io, java.nio, Netty?
23 |
24 | ---
25 |
26 | ### Ответы:
27 |
28 | 1.
29 | 2.
30 | 3.
31 | 4.
32 | 5.
33 | 6.
34 |
35 | ---
36 |
37 | ### Материалы:
38 |
39 | 1. [Howe make a fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo)
40 | 2. [How make a pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)
41 | 3. [What is Docker?] todo: add link about docker
42 |
--------------------------------------------------------------------------------
/lesson-1/PITCHME.md:
--------------------------------------------------------------------------------
1 | # Урок 1
2 |
3 | ## Проектирование архитектуры
4 |
5 | Анализ и обсуждение курсового проекта «Облачное хранилище»
6 |
7 | ---
8 |
9 | ## План Урока
10 |
11 | - Обзор курса;
12 | - Обсуждение курсового проекта «Облачное хранилище»;
13 | - Частичный повтор тем сетевого взаимодействия, сериализации, потоков ввода/вывода при необходимости.
14 |
15 | ---
16 |
17 | # Как организовать сетевое взаимодействие?
18 |
19 | ---
20 |
21 | ## java.io.ServerSocket/Socket;
22 |
23 | - Пакет java.io был представлен в Java 1.0
24 | - InputStream и OutputStream – побайтовое чтение/запись данных
25 | - Reader и Writer – обертки для более удобной работы с чтением/записью
26 | - blocking mode – ожидание окончания сообщения
27 |
28 | ---
29 |
30 | ## java.nio ServerSocketChannel/SocketChannel;
31 |
32 | - Пакет java.nio был представлен в Java 1.4 и обновлен в Java 1.7
33 | - Buffer – чтение/запись "кусками" в единицу времени
34 | - CharsetDecoder – отображение сырых байтов в читаемые символы(кодировка)
35 | - Selector - предоставление возможности multiplexing-а, работа с одним каналом для чтения и записи
36 | - non-blocking mode – чтение того сколько доступно, без ожидания окончания сообщения
37 |
38 | ---
39 |
40 | ## Java фреймворк Netty.
41 |
42 | - Фреймворк построенный по тем же принципам, что и пакет java.nio на неблокирующем чтении/записи через буфер
43 | - ChannelOutboundHandler и ChannelInboundHandler - для потоковой обработки входящих и исходящих данных
44 | - ByteBuf - буфер для чтения и записи
45 |
46 | ---
47 |
48 | # Где и как хранить файлы на сервере?
49 |
50 | - В одном каталоге и отдельно хранить мета информацию о файлах и о том какой файл какому пользователю принадлежит
51 | - Каждому пользователю создать свой подкаталог
52 |
53 | ---
54 |
--------------------------------------------------------------------------------
/lesson-1/dir/2.txt:
--------------------------------------------------------------------------------
1 | hello
2 | world
3 | 310287310
--------------------------------------------------------------------------------
/lesson-1/dir/channel_example_4.txt:
--------------------------------------------------------------------------------
1 | contentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontent
--------------------------------------------------------------------------------
/lesson-1/dir/from.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-1/dir/from.txt
--------------------------------------------------------------------------------
/lesson-1/dir/from_input.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-1/dir/from_input.txt
--------------------------------------------------------------------------------
/lesson-1/dir/out.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-1/dir/out.txt
--------------------------------------------------------------------------------
/lesson-1/dir/subdir0/file.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-1/dir/subdir0/file.txt
--------------------------------------------------------------------------------
/lesson-1/dir/to.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-1/dir/to.txt
--------------------------------------------------------------------------------
/lesson-1/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | java-net-course
7 | ru.daniilazarnov
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | lesson-1
13 |
14 |
15 | 11
16 | 11
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lesson-1/src/main/java/ru/daniilazarnov/Main.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov;
2 |
3 | public class Main {
4 |
5 | public static void main(String[] args) {
6 | System.out.println("Lesson 1");
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/lesson-1/src/test/java/ru/daniilazarnov/FilesExamplesTest.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.junit.jupiter.api.condition.DisabledOnOs;
5 | import org.junit.jupiter.api.condition.OS;
6 |
7 | import java.io.*;
8 | import java.net.URISyntaxException;
9 | import java.net.URL;
10 | import java.nio.channels.FileChannel;
11 | import java.nio.file.*;
12 | import java.nio.file.attribute.BasicFileAttributes;
13 | import java.util.Arrays;
14 | import java.util.List;
15 | import java.util.stream.Stream;
16 |
17 | import static org.junit.jupiter.api.Assertions.*;
18 |
19 | class FilesExamplesTest {
20 |
21 | @Test
22 | void testCopy() throws IOException {
23 | Files.copy(Path.of("dir/from.txt"), Path.of("dir/to.txt"), StandardCopyOption.REPLACE_EXISTING);
24 |
25 | OutputStream outputStream = new FileOutputStream("dir/out.txt");
26 | Files.copy(Path.of("dir/from.txt"), outputStream);
27 |
28 | InputStream inputStream = new FileInputStream("dir/from.txt");
29 | Files.copy(inputStream, Path.of("dir/from_input.txt"), StandardCopyOption.REPLACE_EXISTING);
30 | }
31 |
32 | @Test
33 | void testWalk() throws IOException {
34 | Stream stream = Files.walk(Path.of("../lesson-1/dir"));
35 |
36 | stream.forEach(System.out::println);
37 | }
38 |
39 | @Test
40 | void testFileVisitResult() {
41 | for (FileVisitResult value : FileVisitResult.values()) {
42 | System.out.println(value);
43 | }
44 | }
45 |
46 | @Test
47 | void testWalkFileTree() throws IOException {
48 | Files.walkFileTree(Path.of("../lesson-1/dir"), new FileVisitor() {
49 | @Override
50 | public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
51 | return FileVisitResult.CONTINUE;
52 | }
53 |
54 | @Override
55 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
56 | return FileVisitResult.CONTINUE;
57 | }
58 |
59 | @Override
60 | public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
61 | return FileVisitResult.CONTINUE;
62 | }
63 |
64 | @Override
65 | public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
66 | return FileVisitResult.CONTINUE;
67 | }
68 | });
69 | }
70 |
71 | @Test
72 | void testDeleteEmptyDirectory() throws IOException {
73 | Files.createDirectory(Path.of("empty_dir"));
74 |
75 | assertTrue(Files.exists(Path.of("empty_dir")));
76 |
77 | Files.delete(Path.of("empty_dir"));
78 |
79 | assertFalse(Files.exists(Path.of("empty_dir")));
80 | }
81 |
82 | @Test
83 | void testDeleteNotEmptyDirectory() throws IOException {
84 | Files.createDirectory(Path.of("dir_with_file"));
85 | Files.createFile(Path.of("dir_with_file/file.txt"));
86 |
87 | assertTrue(Files.exists(Path.of("dir_with_file")));
88 | assertThrows(DirectoryNotEmptyException.class, () -> Files.delete(Path.of("dir_with_file")));
89 |
90 | assertTrue(Files.exists(Path.of("dir_with_file")));
91 | assertTrue(Files.exists(Path.of("dir_with_file/file.txt")));
92 |
93 | Files.walkFileTree(Path.of("dir_with_file"), new FileVisitor() {
94 | @Override
95 | public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
96 | return FileVisitResult.CONTINUE;
97 | }
98 |
99 | @Override
100 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
101 | Files.delete(file);
102 | return FileVisitResult.CONTINUE;
103 | }
104 |
105 | @Override
106 | public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
107 | return FileVisitResult.CONTINUE;
108 | }
109 |
110 | @Override
111 | public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
112 | Files.delete(dir);
113 | return FileVisitResult.CONTINUE;
114 | }
115 | });
116 |
117 | assertFalse(Files.exists(Path.of("dir_with_file")));
118 | assertFalse(Files.exists(Path.of("dir_with_file/file.txt")));
119 | }
120 |
121 | @Test
122 | void testFileChannel() throws IOException {
123 | Path srcPath = Path.of("dir/channel_example_1.txt");
124 |
125 | RandomAccessFile src = new RandomAccessFile(srcPath.toFile(), "rw");
126 | FileChannel srcChannel = src.getChannel();
127 |
128 | System.out.println(Files.readString(srcPath));
129 |
130 | RandomAccessFile dest = new RandomAccessFile(Path.of("dir/channel_example_2.txt").toFile(), "rw");
131 | FileChannel destChannel = dest.getChannel();
132 |
133 | srcChannel.transferTo(0, srcChannel.size(), destChannel);
134 |
135 | //DatagramChannel - UDP
136 | //SocketChannel - TCP
137 | //ServerSocketChannel - listen all TCP-connections
138 | }
139 |
140 | @Test
141 | void testTruncate() throws IOException {
142 | Path path = Path.of("dir/channel_example_4.txt");
143 |
144 | RandomAccessFile file = new RandomAccessFile(path.toFile(), "rw");
145 | FileChannel channel = file.getChannel();
146 |
147 | System.out.println(channel.position());
148 | System.out.println();
149 | System.out.println(channel.size());
150 |
151 | channel.truncate(channel.size() - 20);
152 | System.out.println(channel.size());
153 | channel.close();
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/lesson-1/src/test/java/ru/daniilazarnov/PathExamplesTest.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.junit.jupiter.api.condition.DisabledOnOs;
5 | import org.junit.jupiter.api.condition.OS;
6 |
7 | import java.io.File;
8 | import java.io.IOException;
9 | import java.net.URISyntaxException;
10 | import java.net.URL;
11 | import java.nio.file.*;
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | import static org.junit.jupiter.api.Assertions.assertFalse;
16 | import static org.junit.jupiter.api.Assertions.assertTrue;
17 |
18 | class PathExamplesTest {
19 |
20 | @Test
21 | void oldWay() {
22 | File file = new File("/unrealpath/file.txt");
23 | assertFalse(file.exists());
24 | }
25 |
26 | @Test
27 | void readFromResources() throws URISyntaxException {
28 | URL resource = getClass().getClassLoader().getResource("file.txt");
29 | Path path = Paths.get(resource.toURI());
30 |
31 | assertTrue(Files.exists(path));
32 | }
33 |
34 | @Test
35 | void testPath0() {
36 | Path path0 = Paths.get("dir/2.txt");
37 | Path path1 = Paths.get("dir" + File.separator + "2.txt");
38 | Path path2 = Paths.get("dir", "2.txt");
39 |
40 | assertTrue(Files.exists(path0));
41 | assertTrue(Files.exists(path1));
42 | assertTrue(Files.exists(path2));
43 |
44 | Path path = Path.of("/unrealpath/file.txt");
45 | assertFalse(Files.exists(path));
46 | }
47 |
48 | @Test
49 | void testRelativize() {
50 | Path path0 = Paths.get("dir/2.txt");
51 | Path path1 = Paths.get("dir/subdir0/file.txt");
52 |
53 | Path relativize = path0.relativize(path1);
54 | System.out.println(relativize);
55 |
56 | System.out.println(path0);
57 | System.out.println(path1);
58 | }
59 |
60 | @Test
61 | void testResolve() {
62 | Path path0 = Paths.get("dir/subdir");
63 | Path path1 = Paths.get("subdir2");
64 |
65 | // dir/subdir + subdir2
66 | System.out.println(path0.resolve("subdir2"));
67 | System.out.println(path0.resolve(path1));
68 |
69 | // user -> root_dir 76fewf83fwefwfwef192409fwe18 + my_love.jpg
70 |
71 | // dir/subdir2
72 | System.out.println(path0.resolveSibling("subdir2"));
73 | System.out.println(path0.resolveSibling(path1));
74 |
75 | System.out.println(path0);
76 | System.out.println(path1);
77 |
78 | Path path3 = Paths.get("dir/fregergergonsdpkogfnjklfaijpgnljbkflgiofpnljbfk dsgmi");
79 | System.out.println(path3);
80 | }
81 |
82 | @Test
83 | void testStartEndWith() {
84 | Path path0 = Paths.get("dir/subdir");
85 |
86 | assertTrue(path0.startsWith("dir"));
87 | assertTrue(path0.endsWith(Paths.get("subdir")));
88 | }
89 |
90 | @Test
91 | void testIsAbsolute() {
92 | Path path0 = Paths.get("dir/subdir");
93 |
94 | Path absolutePath = path0.toAbsolutePath();
95 | System.out.println(absolutePath);
96 |
97 | assertTrue(absolutePath.isAbsolute());
98 | }
99 |
100 | @Test
101 | void testFileNameParentRoot() {
102 | Path path0 = Paths.get("/dir/subdir");
103 |
104 | System.out.println(path0.getFileName());
105 | System.out.println(path0.getParent());
106 | System.out.println(path0.getRoot());
107 | }
108 |
109 | @Test
110 | void testCount() {
111 | Path path0 = Paths.get("/dir/subdir/subsubdir");
112 |
113 | System.out.println(path0.getNameCount());
114 | System.out.println(path0.getName(0));
115 | System.out.println(path0.getName(path0.getNameCount() - 1));
116 | System.out.println(path0.subpath(1, path0.getNameCount()));
117 | }
118 |
119 | @Test
120 | void testNormalize() {
121 | Path path0 = Paths.get("/../../../dir/subdir");
122 |
123 | System.out.println(path0.normalize());
124 | }
125 |
126 | @Test
127 | void testUri() {
128 | Path path0 = Paths.get("dir/subdir");
129 |
130 | System.out.println(path0.toUri());
131 | System.out.println(path0.toFile());
132 | }
133 |
134 | @Test
135 | void nameIterator() {
136 | Path path0 = Paths.get("dir/subdir");
137 |
138 | path0.iterator().forEachRemaining(System.out::println);
139 | }
140 |
141 | @Test
142 | void testFileSystem() {
143 | Path path = Paths.get("dir/2.txt");
144 |
145 | FileSystem fileSystem = path.getFileSystem();
146 |
147 | System.out.println(fileSystem.supportedFileAttributeViews());
148 | System.out.println(fileSystem);
149 | }
150 |
151 | @Test
152 | @DisabledOnOs(OS.WINDOWS)
153 | void testExists() throws IOException {
154 | Path path = Paths.get("dir/2.txt");
155 |
156 | assertTrue(Files.exists(path));
157 |
158 | assertTrue(Files.isRegularFile(path));
159 | assertTrue(Files.isWritable(path));
160 |
161 | assertFalse(Files.isSymbolicLink(path));
162 | assertFalse(Files.isExecutable(path));
163 | assertFalse(Files.isHidden(path));
164 | }
165 |
166 | @Test
167 | void testIs() throws IOException {
168 | Path path0 = Paths.get("dir");
169 | Path path1 = Paths.get("dir");
170 | assertTrue(Files.isDirectory(path0));
171 | assertTrue(Files.isSameFile(path0, path1));
172 | }
173 |
174 | @Test
175 | void testWrite() throws IOException {
176 | Path path = Paths.get("dir/2.txt");
177 |
178 | Files.deleteIfExists(path);
179 | Files.createFile(path);
180 |
181 | Files.write(path, List.of("hello", "world"), StandardOpenOption.WRITE);
182 | Files.writeString(path, "310287310", StandardOpenOption.APPEND);
183 | }
184 |
185 | @Test
186 | void testRead() throws IOException {
187 | Path path = Paths.get("dir/2.txt");
188 |
189 | System.out.println(Arrays.toString(Files.readAllBytes(path)));
190 | System.out.println(Files.readAllLines(path));
191 | System.out.println(Files.readString(path));
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/lesson-1/src/test/resources/file.txt:
--------------------------------------------------------------------------------
1 | resource
2 |
--------------------------------------------------------------------------------
/lesson-2/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | java-net-course
7 | ru.daniilazarnov
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | lesson-2
13 |
14 |
15 | 11
16 | 11
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lesson-2/slides/PRESENTATION.md:
--------------------------------------------------------------------------------
1 | # What about java.nio.Buffer?
2 |
3 | ## "Fill" and "Drain"
4 |
5 | Java NIO Buffer manipulation is done in two contexts, "Fill state" and "Drain state".
6 | "Fill state" means that data is put into the buffer and "Drain state" that data in the buffer is retrieved outside.
7 | (But data is not removed from the buffer during "Drain state")
8 |
9 | ## Operations
10 |
11 | - flip() -
12 | - rewind() -
13 | - mark() -
14 | - reset() -
15 | - compact() -
16 |
17 | ## Examples
18 |
19 | When a new NIO buffer is created, it starts in "Fill state", which may be reasonable because if it starts in "Drain state", no data is available:
20 |
21 | 
22 |
23 | After putting some values, "position" of the buffer is advanced by seven, the length of "JDK api" and "limit" remains unchanged.
24 | Now that some values are added, we can retrieve them from the buffer, and so the state is converted into "Drain state" by calling "flip()":
25 |
26 | 
27 |
28 | "flipping" sets "limit" value to "position" and then "position" value to zero. "limit" changes only when the buffer state changes between "fill" and "drain", and you should never exceed "limit" regardless of the state, otherwise an exception (BufferOverflowException or BufferUnderFlowException) is thrown:
29 |
30 | 
31 |
32 | Five charactes are retrieved from buffer and then filled into a character array of which length is five. ( Two more still remains, "pi") "position" of the buffer is set to 5 and next operation will be done from here to "limit".
33 | If data needs to be copied repeatedly, we have to call "rewind():
34 |
35 | 
36 |
37 | It set "position" value of the buffer to zero(but does not touch "limit" value.) After calling rewind(), we can copy the same data from the buffer.
38 | Below picture shows another version of "get()" having two int parameters, one is the index of "dest" array and the other is length of data to be copied. So it has effect on "dest' array, not buffer itself except the "position" value of the buffer is changed.
39 |
40 | 
41 |
42 | To fill the buffer with data to follow, switch the state using "compact()".
43 |
44 | 
45 |
46 | "compact()" makes two changes to the buffer.
47 |
48 | 1) copies the valid data(" api") to the beginning of the buffer, resulting data between 0 and 4(length of " api") overwrited.
49 | 2) "position" is set next the valid data(" api") and "limit" to the capacity, 10.
50 |
51 | Making the valid data " api" located at the head of the buffer, subsequent "filling" start from "position", resulting in the " api" undamaged for following "Drain state".
52 | "mark()" leaves trace of "position" value for later use.
53 |
54 | 
55 |
56 | There is no way to get "mark" value when looking at the Buffer api because it is just a sign and doesn't have to do.
57 | While manipulating the buffer, if you have to move "position" value back or cancel the manipulation, calling "reset()" do it for you.
58 |
59 | 
60 |
61 | Be sure that "reset()" always sets "position" back to the "mark", so if there is no mark(if you never called "mark()" before), it will throw "java.nio.InvalidMarkException". Once you call "mark()", it remains valid and "reset()" works without exceptions, until mark is smaller than "position".
62 |
63 | 
64 |
65 | "mark" value set by "mark()" is invalidated only when "mark" is greater than "position" or "limit".
66 | "mark" validation is check whenever "position" or "limit" changes. If "mark" set by former "mark()" is smaller than "position" and "limit", then it continue to be valid regardless of the state.
67 | In fact, the methods mentioned above can be called regardless of "Fill" and "Drain" state. If it is needed, "get(..)" may be called in "Fill state". But, in most of cases, "putting data into buffer" leads to "retrieving data from buffer" and vise versa, which groups the methods naturally by the context they are used.
68 |
69 | ## Links
70 |
71 | - [Source](https://javafreak.tistory.com/211) - Original article
72 | - [Documentation](https://docs.oracle.com/javase/6/docs/api/java/nio/Buffer.html) - Oracle documentation
73 |
--------------------------------------------------------------------------------
/lesson-2/slides/img/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img.png
--------------------------------------------------------------------------------
/lesson-2/slides/img/img_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img_1.png
--------------------------------------------------------------------------------
/lesson-2/slides/img/img_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img_2.png
--------------------------------------------------------------------------------
/lesson-2/slides/img/img_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img_3.png
--------------------------------------------------------------------------------
/lesson-2/slides/img/img_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img_4.png
--------------------------------------------------------------------------------
/lesson-2/slides/img/img_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img_5.png
--------------------------------------------------------------------------------
/lesson-2/slides/img/img_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img_6.png
--------------------------------------------------------------------------------
/lesson-2/slides/img/img_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img_7.png
--------------------------------------------------------------------------------
/lesson-2/slides/img/img_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-2/slides/img/img_8.png
--------------------------------------------------------------------------------
/lesson-2/src/main/java/ru/daniilazarnov/NioChatServerExample.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov;
2 |
3 | import java.io.IOException;
4 | import java.net.InetSocketAddress;
5 | import java.nio.ByteBuffer;
6 | import java.nio.channels.SelectionKey;
7 | import java.nio.channels.Selector;
8 | import java.nio.channels.ServerSocketChannel;
9 | import java.nio.channels.SocketChannel;
10 | import java.util.Iterator;
11 |
12 | public final class NioChatServerExample implements Runnable {
13 |
14 | public static final int PORT = 8189;
15 | private final ServerSocketChannel serverSocketChannel;
16 | private final Selector selector;
17 | private final ByteBuffer buf = ByteBuffer.allocate(256);
18 | private int acceptedClientIndex = 1;
19 | private final ByteBuffer welcomeBuf = ByteBuffer.wrap("Добро пожаловать в чат!\n".getBytes());
20 |
21 | NioChatServerExample() throws IOException {
22 | this.serverSocketChannel = ServerSocketChannel.open();
23 | this.serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
24 | this.serverSocketChannel.configureBlocking(false);
25 | this.selector = Selector.open();
26 | this.serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
27 | }
28 |
29 | public static void main(String[] args) throws IOException {
30 | new Thread(new NioChatServerExample()).start();
31 | }
32 |
33 | @Override
34 | public void run() {
35 | try {
36 | System.out.println("Сервер запущен (Порт: 8189)");
37 | Iterator iter;
38 | SelectionKey key;
39 | while (this.serverSocketChannel.isOpen()) {
40 | selector.select();
41 | iter = this.selector.selectedKeys().iterator();
42 | while (iter.hasNext()) {
43 | key = iter.next();
44 | iter.remove();
45 | if (key.isAcceptable()) {
46 | handleAccept(key);
47 | }
48 | if (key.isReadable()) {
49 | handleRead(key);
50 | }
51 | }
52 | }
53 | } catch (IOException e) {
54 | e.printStackTrace();
55 | }
56 | }
57 |
58 | private void handleAccept(SelectionKey key) throws IOException {
59 | SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
60 | String clientName = "Клиент #" + acceptedClientIndex;
61 | acceptedClientIndex++;
62 | sc.configureBlocking(false);
63 | sc.register(selector, SelectionKey.OP_READ, clientName);
64 | sc.write(welcomeBuf);
65 | welcomeBuf.rewind();
66 | System.out.println("Подключился новый клиент " + clientName);
67 | }
68 |
69 | private void handleRead(SelectionKey key) throws IOException {
70 | SocketChannel ch = (SocketChannel) key.channel();
71 | StringBuilder sb = new StringBuilder();
72 |
73 | buf.clear();
74 | int read = 0;
75 | while ((read = ch.read(buf)) > 0) {
76 | buf.flip();
77 | byte[] bytes = new byte[buf.limit()];
78 | buf.get(bytes);
79 | sb.append(new String(bytes));
80 | buf.clear();
81 | }
82 | String msg;
83 | if (read < 0) {
84 | msg = key.attachment() + " покинул чат\n";
85 | ch.close();
86 | } else {
87 | msg = key.attachment() + ": " + sb.toString();
88 | }
89 |
90 | System.out.println(msg);
91 | broadcastMessage(msg);
92 | }
93 |
94 | private void broadcastMessage(String msg) throws IOException {
95 | ByteBuffer msgBuf = ByteBuffer.wrap(msg.getBytes());
96 | for (SelectionKey key : selector.keys()) {
97 | if (key.isValid() && key.channel() instanceof SocketChannel) {
98 | SocketChannel sch = (SocketChannel) key.channel();
99 | sch.write(msgBuf);
100 | msgBuf.rewind();
101 | }
102 | }
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/lesson-2/src/test/java/ru/daniilazarnov/BufferExamplesTest.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.io.FileNotFoundException;
6 | import java.io.IOException;
7 | import java.io.RandomAccessFile;
8 | import java.nio.Buffer;
9 | import java.nio.BufferUnderflowException;
10 | import java.nio.ByteBuffer;
11 | import java.nio.IntBuffer;
12 | import java.nio.channels.FileChannel;
13 | import java.nio.file.*;
14 | import java.nio.file.attribute.BasicFileAttributes;
15 | import java.util.stream.Stream;
16 |
17 | import static org.junit.jupiter.api.Assertions.*;
18 |
19 | class BufferExamplesTest {
20 |
21 | @Test
22 | void testBuffer0() {
23 | byte[] arr = {10, 20, 30, 40, 50};
24 | ByteBuffer buffer = ByteBuffer.wrap(arr);
25 |
26 | System.out.println("capacity: " + buffer.capacity());
27 | System.out.println("limit: " + buffer.limit());
28 | System.out.println("position: " + buffer.position());
29 | System.out.println(buffer);
30 | }
31 |
32 | @Test
33 | void testBuffer1() {
34 | byte[] arr = {10, 20, 30, 40, 50};
35 | ByteBuffer buffer = ByteBuffer.wrap(arr);
36 |
37 | System.out.println();
38 | System.out.println("get: " + buffer.get());
39 | System.out.println("capacity: " + buffer.capacity());
40 | System.out.println("limit: " + buffer.limit());
41 | System.out.println("position: " + buffer.position());
42 | System.out.println(buffer);
43 |
44 | System.out.println();
45 | System.out.println("get: " + buffer.get());
46 | System.out.println("capacity: " + buffer.capacity());
47 | System.out.println("limit: " + buffer.limit());
48 | System.out.println("position: " + buffer.position());
49 | System.out.println(buffer);
50 | }
51 |
52 | @Test
53 | void testBuffer2() {
54 | byte[] arr = {10, 20, 30, 40, 50};
55 | ByteBuffer buffer = ByteBuffer.wrap(arr);
56 |
57 | System.out.println("get: " + buffer.get());
58 | System.out.println("get: " + buffer.get());
59 | System.out.println("position: " + buffer.position());
60 | System.out.println();
61 |
62 | buffer.rewind();
63 | System.out.println("capacity: " + buffer.capacity());
64 | System.out.println("limit: " + buffer.limit());
65 | System.out.println("position: " + buffer.position());
66 | System.out.println(buffer);
67 | System.out.println("get: " + buffer.get());
68 | System.out.println("get: " + buffer.get());
69 | }
70 |
71 | @Test
72 | void testBuffer3() {
73 | byte[] arr = {10, 20, 30, 40, 50};
74 | ByteBuffer buffer = ByteBuffer.wrap(arr);
75 |
76 | System.out.println("get: " + buffer.get());
77 | System.out.println("position: " + buffer.position());
78 | buffer.mark();
79 | System.out.println("get: " + buffer.get());
80 | System.out.println("position: " + buffer.position());
81 | buffer.reset();
82 | System.out.println("position: " + buffer.position());
83 |
84 | buffer.clear();
85 | System.out.println("capacity: " + buffer.capacity());
86 | System.out.println("limit: " + buffer.limit());
87 | System.out.println("position: " + buffer.position());
88 | }
89 |
90 | @Test
91 | void testBuffer4() {
92 | byte[] arr = {10, 20, 30, 40, 50};
93 | ByteBuffer buffer = ByteBuffer.wrap(arr);
94 |
95 | System.out.println(buffer.get());
96 | System.out.println(buffer.get());
97 | System.out.println();
98 | buffer.compact();
99 | System.out.println("capacity: " + buffer.capacity());
100 | System.out.println("limit: " + buffer.limit());
101 | System.out.println("position: " + buffer.position());
102 | System.out.println(buffer);
103 | }
104 |
105 | @Test
106 | void testBuffer5() {
107 | byte[] arr = {10, 20, 30, 40, 50};
108 | ByteBuffer buffer = ByteBuffer.wrap(arr);
109 |
110 | System.out.println(buffer.get());
111 | System.out.println(buffer.get());
112 | System.out.println("capacity: " + buffer.capacity());
113 | System.out.println("limit: " + buffer.limit());
114 | System.out.println("position: " + buffer.position());
115 | System.out.println();
116 | buffer.flip();
117 | System.out.println("capacity: " + buffer.capacity());
118 | System.out.println("limit: " + buffer.limit());
119 | System.out.println("position: " + buffer.position());
120 | System.out.println(buffer);
121 | }
122 |
123 | @Test
124 | void testReadWithBuffer() throws IOException {
125 | Path srcPath = Path.of("src/main/java/ru/daniilazarnov/Main.java");
126 |
127 | RandomAccessFile src = new RandomAccessFile(srcPath.toFile(), "rw");
128 | FileChannel srcChannel = src.getChannel();
129 |
130 | ByteBuffer buf = ByteBuffer.allocate(48);
131 | System.out.println("position: " + buf.position());
132 | int bytesRead = srcChannel.read(buf);
133 | System.out.println("position: " + buf.position());
134 | System.out.println("capacity: " + buf.capacity());
135 | System.out.println("limit: " + buf.limit());
136 | while (bytesRead != -1) {
137 | buf.flip();
138 |
139 | while (buf.hasRemaining()) {
140 | System.out.print((char) buf.get());
141 | }
142 | buf.clear();
143 | bytesRead = srcChannel.read(buf);
144 | System.out.println("position: " + buf.position());
145 | }
146 | srcChannel.close();
147 | }
148 |
149 | @Test
150 | void testWrite() {
151 | String newData = "New String to write to file..." + System.currentTimeMillis();
152 |
153 | ByteBuffer buf = ByteBuffer.allocate(12);
154 | int iter = 0;
155 |
156 | byte[] bytes = newData.getBytes();
157 | for (int i = 0; i < bytes.length;) {
158 | if (buf.position() < buf.capacity()) {
159 | buf.put(bytes[i]);
160 | i++;
161 | } else {
162 | System.out.println("Before flip: position: " + buf.position() + " limit: " + buf.limit());
163 | buf.flip();
164 | System.out.println("After flip: position: " + buf.position() + " limit: " + buf.limit());
165 |
166 | System.out.println("Iteration:" + iter);
167 | iter++;
168 | while (buf.hasRemaining()) {
169 | System.out.print((char) buf.get());
170 | }
171 | System.out.println();
172 | System.out.println("After read: position: " + buf.position() + " limit: " + buf.limit());
173 | buf.clear();
174 | System.out.println("After clear: position: " + buf.position() + " limit: " + buf.limit());
175 | System.out.println();
176 | }
177 | }
178 | System.out.println("Before flip: position: " + buf.position() + " limit: " + buf.limit());
179 | buf.flip();
180 | //[12][12][312][42][34][34][55][44]
181 | System.out.println("After flip: position: " + buf.position() + " limit: " + buf.limit());
182 |
183 | System.out.println("Iteration:" + iter);
184 | while (buf.hasRemaining()) {
185 | System.out.print((char) buf.get());
186 | }
187 | System.out.println();
188 | System.out.println("After read: position: " + buf.position() + " limit: " + buf.limit());
189 | buf.clear();
190 | System.out.println("After clear: position: " + buf.position() + " limit: " + buf.limit());
191 | System.out.println();
192 | }
193 |
194 | @Test
195 | void testBuffer7() {
196 |
197 | //int - 32bit
198 | //byte - 8bit
199 | //long - 64bit
200 |
201 | byte[] arr = {10, 20, 30, 40, 50};
202 | ByteBuffer buffer = ByteBuffer.wrap(arr);
203 |
204 | System.out.println(buffer.getInt());
205 | System.out.println("capacity: " + buffer.capacity());
206 | System.out.println("limit: " + buffer.limit());
207 | System.out.println("position: " + buffer.position());
208 | }
209 |
210 | @Test
211 | void testBuffer8() {
212 | byte[] arr = {10, 20, 30, 40, 50};
213 | ByteBuffer buffer = ByteBuffer.wrap(arr);
214 |
215 | assertThrows(BufferUnderflowException.class, buffer::getLong);
216 | }
217 |
218 | @Test
219 | void testBufferProtocol() {
220 |
221 | // message length in bytes - int ; information - ???
222 | byte[] arr = {0, 0, 0, 10, 65, 65, 65, 65, 65, 65, 65, 65, 65, 20, 30, 40, 50, 10, 10, 20, 30, 40, 50, 10};
223 | //System.out.println(arr.length);
224 | ByteBuffer buffer = ByteBuffer.wrap(arr);
225 |
226 | System.out.println();
227 |
228 | int messageLength = buffer.getInt();
229 |
230 | for (int i = 0; i < messageLength; i++) {
231 | System.out.print((char) buffer.get());
232 | }
233 |
234 | System.out.println();
235 |
236 | System.out.println("capacity: " + buffer.capacity());
237 | System.out.println("limit: " + buffer.limit());
238 | System.out.println("position: " + buffer.position());
239 | }
240 |
241 | }
242 |
--------------------------------------------------------------------------------
/lesson-3/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | java-net-course
7 | ru.daniilazarnov
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | lesson-3
13 |
14 |
15 | 11
16 | 11
17 |
18 |
19 |
20 |
21 | io.netty
22 | netty-all
23 | 4.1.42.Final
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/lesson-3/slides/PRESENTATION.md:
--------------------------------------------------------------------------------
1 | # What is Netty?
2 |
3 | ## Структура
4 |
5 | - Обзор фреймворка Netty;
6 | - Структура Netty-сервера;
7 | - Написание серверов;
8 | - Написание клиентской части;
9 | - Обмен сообщениями с помощью ByteBuf и POJO.
10 |
11 | ## Домашнее задание
12 |
13 | - Продолжаем писать проект
14 |
15 | ## Ссылки
16 |
17 | - [C10k_problem](https://en.wikipedia.org/wiki/C10k_problem) 10_000 потоков
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/auth/AuthClient.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.auth;
2 |
3 | import io.netty.handler.codec.serialization.ObjectEncoderOutputStream;
4 |
5 | import java.net.Socket;
6 |
7 | public class AuthClient {
8 |
9 | public static final int PORT = 8189;
10 | public static final String HOST = "localhost";
11 |
12 | public static void main(String[] args) {
13 | try (Socket socket = new Socket(HOST, PORT);
14 | ObjectEncoderOutputStream out = new ObjectEncoderOutputStream(socket.getOutputStream())) {
15 |
16 | out.writeObject("/auth Vasya");
17 | out.writeObject("Hello");
18 | } catch (Exception e) {
19 | e.printStackTrace();
20 | }
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/auth/AuthHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.auth;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 |
6 | import java.util.Set;
7 |
8 | class AuthHandler extends ChannelInboundHandlerAdapter {
9 |
10 | private final Set authorizedClients = Set.of("Vasya");
11 |
12 | private boolean authOk = false;
13 |
14 | @Override
15 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
16 | String input = (String) msg;
17 |
18 | if (authOk) {
19 | ctx.fireChannelRead(input);
20 | return;
21 | }
22 | if (input.split(" ")[0].equals("/auth")) {
23 | String username = input.split(" ")[1];
24 | if (authorizedClients.contains(username)) {
25 | authOk = true;
26 | ctx.pipeline().addLast(new MainHandler(username));
27 | }
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/auth/AuthServer.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.auth;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelOption;
7 | import io.netty.channel.EventLoopGroup;
8 | import io.netty.channel.nio.NioEventLoopGroup;
9 | import io.netty.channel.socket.SocketChannel;
10 | import io.netty.channel.socket.nio.NioServerSocketChannel;
11 | import io.netty.handler.codec.serialization.ObjectDecoder;
12 |
13 | public class AuthServer implements Runnable {
14 |
15 | public static final int MAX_OBJECT_SIZE = 1024 * 1024;
16 | public static final int INET_PORT = 8189;
17 |
18 | @Override
19 | public void run() {
20 | EventLoopGroup bossGroup = new NioEventLoopGroup();
21 | EventLoopGroup workerGroup = new NioEventLoopGroup();
22 | try {
23 | ServerBootstrap b = new ServerBootstrap();
24 | b.group(bossGroup, workerGroup)
25 | .channel(NioServerSocketChannel.class)
26 | .childHandler(new ChannelInitializer() {
27 | @Override
28 | public void initChannel(SocketChannel ch) {
29 | ch.pipeline().addLast(new ObjectDecoder(MAX_OBJECT_SIZE, null), new AuthHandler());
30 | }
31 | })
32 | .childOption(ChannelOption.SO_KEEPALIVE, true);
33 | ChannelFuture f = b.bind(INET_PORT).sync();
34 | f.channel().closeFuture().sync();
35 | } catch (InterruptedException e) {
36 | e.printStackTrace();
37 | } finally {
38 | workerGroup.shutdownGracefully();
39 | bossGroup.shutdownGracefully();
40 | }
41 | }
42 |
43 | public static void main(String[] args) throws Exception {
44 | new Thread(new AuthServer()).start();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/auth/MainHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.auth;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 |
6 | class MainHandler extends ChannelInboundHandlerAdapter {
7 |
8 | private final String username;
9 |
10 | MainHandler(String username) {
11 | this.username = username;
12 | }
13 |
14 | @Override
15 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
16 | String input = (String) msg;
17 | System.out.println(username + ": " + input);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/hello/HelloServer.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.hello;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 |
5 | import io.netty.channel.*;
6 | import io.netty.channel.nio.NioEventLoopGroup;
7 | import io.netty.channel.socket.SocketChannel;
8 | import io.netty.channel.socket.nio.NioServerSocketChannel;
9 |
10 | public final class HelloServer {
11 |
12 | public static final int INET_PORT = 8189;
13 |
14 | public static void main(String[] args) throws Exception {
15 | new HelloServer().run();
16 | }
17 |
18 | public void run() throws Exception {
19 | EventLoopGroup bossGroup = new NioEventLoopGroup();
20 | EventLoopGroup workerGroup = new NioEventLoopGroup(2);
21 | try {
22 | ServerBootstrap b = new ServerBootstrap();
23 | b.group(bossGroup, workerGroup)
24 | .channel(NioServerSocketChannel.class)
25 | .childHandler(new ChannelInitializer() {
26 | @Override
27 | public void initChannel(SocketChannel ch) {
28 | ch.pipeline().addLast(new HelloServerHandler());
29 | }
30 | });
31 | ChannelFuture f = b.bind(INET_PORT).sync();
32 | f.channel().closeFuture().sync();
33 | } finally {
34 | workerGroup.shutdownGracefully();
35 | bossGroup.shutdownGracefully();
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/hello/HelloServerHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.hello;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 |
7 | public class HelloServerHandler extends ChannelInboundHandlerAdapter {
8 |
9 | private static int index = 0;
10 |
11 | private String name;
12 |
13 | @Override
14 | public void channelActive(ChannelHandlerContext ctx) {
15 | name = "Сlient №" + index;
16 | index++;
17 | System.out.println("Active pipeline for: " + name);
18 | }
19 |
20 | @Override
21 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
22 | System.out.println(name + ": " + Thread.currentThread());
23 |
24 | ByteBuf byteBuf = (ByteBuf) msg;
25 | byte[] data = new byte[byteBuf.readableBytes()];
26 | byteBuf.readBytes(data);
27 |
28 | System.out.println(name + ": " + new String(data));
29 |
30 | byte[] arr = "Hello ".getBytes();
31 | ByteBuf buf = ctx.alloc().buffer(arr.length);
32 | buf.writeBytes(arr);
33 |
34 | ctx.writeAndFlush(buf);
35 | }
36 |
37 | @Override
38 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
39 | cause.printStackTrace();
40 | ctx.close();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/hello/IoClient.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.hello;
2 |
3 | import java.io.DataOutputStream;
4 | import java.net.Socket;
5 | import java.nio.charset.StandardCharsets;
6 | import java.util.Scanner;
7 |
8 | public class IoClient {
9 |
10 | public static final int PORT = 8189;
11 | public static final String HOST = "localhost";
12 |
13 | public static void main(String[] args) {
14 | new IoClient().run();
15 | }
16 |
17 | void run() {
18 | Scanner scanner = new Scanner(System.in);
19 |
20 | String input = scanner.next();
21 |
22 | try (Socket socket = new Socket(HOST, PORT);
23 | DataOutputStream out = new DataOutputStream(socket.getOutputStream());
24 | Scanner in = new Scanner(socket.getInputStream())) {
25 |
26 | out.write(input.getBytes(StandardCharsets.UTF_8));
27 |
28 | while (in.hasNext()) {
29 | String output = in.next();
30 | System.out.println("Received message: " + output);
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/pipeline/MyClient.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.pipeline;
2 |
3 | import java.io.DataOutputStream;
4 | import java.net.Socket;
5 | import java.util.Scanner;
6 |
7 | public class MyClient {
8 |
9 | public static final int PORT = 8189;
10 | public static final String LOCALHOST = "localhost";
11 | public static final int MAGIC_NUMBER = 21;
12 |
13 | public static void main(String[] args) {
14 | try (Socket socket = new Socket(LOCALHOST, PORT);
15 | DataOutputStream out = new DataOutputStream(socket.getOutputStream());
16 | Scanner in = new Scanner(socket.getInputStream())) {
17 |
18 | out.write(new byte[]{MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER});
19 | String x = in.nextLine();
20 | System.out.println("A: " + x);
21 | } catch (Exception e) {
22 | e.printStackTrace();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/pipeline/MyServer.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.pipeline;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.EventLoopGroup;
7 | import io.netty.channel.nio.NioEventLoopGroup;
8 | import io.netty.channel.socket.SocketChannel;
9 | import io.netty.channel.socket.nio.NioServerSocketChannel;
10 | import ru.daniilazarnov.pipeline.handlers.in.FinalInboundHandler;
11 | import ru.daniilazarnov.pipeline.handlers.in.FirstInboundHandler;
12 | import ru.daniilazarnov.pipeline.handlers.in.GatewayInboundHandler;
13 | import ru.daniilazarnov.pipeline.handlers.in.SecondInboundHandler;
14 | import ru.daniilazarnov.pipeline.handlers.out.StringToStringOutboundHandler;
15 | import ru.daniilazarnov.pipeline.handlers.out.StringToByteBufOutboundHandler;
16 |
17 | public class MyServer {
18 |
19 | public static final int INET_PORT = 8189;
20 |
21 | public void run() throws Exception {
22 | EventLoopGroup bossGroup = new NioEventLoopGroup();
23 | EventLoopGroup workerGroup = new NioEventLoopGroup();
24 |
25 | try {
26 | ServerBootstrap b = new ServerBootstrap();
27 | b.group(bossGroup, workerGroup)
28 | .channel(NioServerSocketChannel.class)
29 | .childHandler(new ChannelInitializer() {
30 | @Override
31 | public void initChannel(SocketChannel ch) {
32 | ch.pipeline()
33 | .addLast(new StringToByteBufOutboundHandler()) // 1 - outbound
34 | .addLast(new FirstInboundHandler()) // 1 - inbound
35 | .addLast(new StringToStringOutboundHandler()) // 2 - outbound
36 | .addLast(new SecondInboundHandler()) // 2 - inbound
37 | .addLast(new GatewayInboundHandler()) // 3 - inbound
38 | .addLast(new FinalInboundHandler()); // 4 inbound
39 | }
40 | });
41 | ChannelFuture f = b.bind(INET_PORT).sync();
42 | f.channel().closeFuture().sync();
43 | } finally {
44 | workerGroup.shutdownGracefully();
45 | bossGroup.shutdownGracefully();
46 | }
47 | }
48 |
49 | public static void main(String[] args) throws Exception {
50 | new MyServer().run();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/pipeline/handlers/in/FinalInboundHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.pipeline.handlers.in;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 |
6 | import java.nio.file.Files;
7 | import java.nio.file.Paths;
8 |
9 | public class FinalInboundHandler extends ChannelInboundHandlerAdapter {
10 |
11 | @Override
12 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
13 | System.out.println("final");
14 | byte[] arr = (byte[]) msg;
15 | Files.write(Paths.get("1.txt"), arr);
16 | System.out.println("Сообщение записано в файл");
17 | ctx.writeAndFlush("Java");
18 | }
19 |
20 | @Override
21 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
22 | cause.printStackTrace();
23 | ctx.close();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/pipeline/handlers/in/FirstInboundHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.pipeline.handlers.in;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 |
7 | import java.util.Arrays;
8 |
9 | public class FirstInboundHandler extends ChannelInboundHandlerAdapter {
10 |
11 | public static final int MESSAGE_SIZE = 3;
12 |
13 | @Override
14 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
15 | System.out.println("first");
16 | ByteBuf buf = (ByteBuf) msg;
17 | if (buf.readableBytes() < MESSAGE_SIZE) {
18 | buf.release();
19 | ctx.writeAndFlush("hahahah");
20 | }
21 | byte[] data = new byte[MESSAGE_SIZE];
22 | buf.readBytes(data);
23 | buf.release();
24 | System.out.println(Arrays.toString(data));
25 | ctx.fireChannelRead(data);
26 | }
27 |
28 | @Override
29 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
30 | cause.printStackTrace();
31 | ctx.close();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/pipeline/handlers/in/GatewayInboundHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.pipeline.handlers.in;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 |
6 | import java.util.Arrays;
7 |
8 | public class GatewayInboundHandler extends ChannelInboundHandlerAdapter {
9 |
10 | public static final int MAGIC_NUMBER = 66;
11 |
12 | @Override
13 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
14 | cause.printStackTrace();
15 | ctx.close();
16 | }
17 |
18 | @Override
19 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
20 | System.out.println("gateway");
21 | int sum = 0;
22 | byte[] arr = (byte[]) msg;
23 | for (byte b : arr) {
24 | sum += b;
25 | }
26 | if (sum == MAGIC_NUMBER) {
27 | ctx.fireChannelRead(arr);
28 | } else {
29 | System.out.println("Сообщение сломано: " + Arrays.toString(arr));
30 | ctx.writeAndFlush("Битое сообщение\n");
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/pipeline/handlers/in/SecondInboundHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.pipeline.handlers.in;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 |
6 | import java.util.Arrays;
7 |
8 | public class SecondInboundHandler extends ChannelInboundHandlerAdapter {
9 |
10 | @Override
11 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
12 | System.out.println("second");
13 | byte[] arr = (byte[]) msg;
14 | for (int i = 0; i < arr.length; i++) {
15 | arr[i]++;
16 | }
17 | System.out.println("Второй шаг: " + Arrays.toString(arr));
18 | ctx.fireChannelRead(arr);
19 | }
20 |
21 | @Override
22 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
23 | cause.printStackTrace();
24 | ctx.close();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/pipeline/handlers/out/StringToByteBufOutboundHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.pipeline.handlers.out;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelOutboundHandlerAdapter;
6 | import io.netty.channel.ChannelPromise;
7 |
8 | public class StringToByteBufOutboundHandler extends ChannelOutboundHandlerAdapter {
9 |
10 | // write -> write -> write
11 | // read -> read -> read
12 |
13 | @Override
14 | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
15 | System.out.println("string to byte 2");
16 | String str = (String) msg;
17 | byte[] arr = (str + " StringToByteBufHandler2 ").getBytes();
18 | ByteBuf buf = ctx.alloc().buffer(arr.length);
19 | buf.writeBytes(arr);
20 | ctx.writeAndFlush(buf);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/pipeline/handlers/out/StringToStringOutboundHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.pipeline.handlers.out;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelOutboundHandlerAdapter;
5 | import io.netty.channel.ChannelPromise;
6 |
7 | public class StringToStringOutboundHandler extends ChannelOutboundHandlerAdapter {
8 |
9 | @Override
10 | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
11 | System.out.println("string to byte");
12 | ctx.writeAndFlush(msg + "StringToByteBufHandler ");
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/proto/client/Network.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.proto.client;
2 |
3 | import io.netty.bootstrap.Bootstrap;
4 | import io.netty.channel.Channel;
5 | import io.netty.channel.ChannelFuture;
6 | import io.netty.channel.ChannelInitializer;
7 | import io.netty.channel.EventLoopGroup;
8 | import io.netty.channel.nio.NioEventLoopGroup;
9 | import io.netty.channel.socket.SocketChannel;
10 | import io.netty.channel.socket.nio.NioSocketChannel;
11 |
12 | import java.net.InetSocketAddress;
13 | import java.util.concurrent.CountDownLatch;
14 |
15 | public final class Network {
16 |
17 | public static final int PORT = 8189;
18 | private Channel currentChannel;
19 |
20 | public Channel getCurrentChannel() {
21 | return currentChannel;
22 | }
23 |
24 | public void start(CountDownLatch countDownLatch) {
25 | EventLoopGroup group = new NioEventLoopGroup();
26 | try {
27 | Bootstrap clientBootstrap = new Bootstrap();
28 | clientBootstrap.group(group)
29 | .channel(NioSocketChannel.class)
30 | .remoteAddress(new InetSocketAddress("localhost", PORT))
31 | .handler(new ChannelInitializer() {
32 | @Override
33 | protected void initChannel(SocketChannel socketChannel) {
34 | socketChannel.pipeline().addLast();
35 | currentChannel = socketChannel;
36 | }
37 | });
38 | ChannelFuture channelFuture = clientBootstrap.connect().sync();
39 | countDownLatch.countDown();
40 | channelFuture.channel().closeFuture().sync();
41 | } catch (Exception e) {
42 | e.printStackTrace();
43 | } finally {
44 | try {
45 | group.shutdownGracefully().sync();
46 | } catch (InterruptedException e) {
47 | e.printStackTrace();
48 | }
49 | }
50 | }
51 |
52 | public void stop() {
53 | currentChannel.close();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/proto/client/ProtoClient.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.proto.client;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.buffer.ByteBufAllocator;
5 | import io.netty.channel.*;
6 |
7 | import java.io.IOException;
8 | import java.nio.charset.StandardCharsets;
9 | import java.nio.file.Files;
10 | import java.nio.file.Path;
11 | import java.nio.file.Paths;
12 | import java.util.concurrent.CountDownLatch;
13 |
14 | public class ProtoClient {
15 |
16 | public static final byte MAGIC_BYTE = (byte) 25;
17 | private final Network network;
18 |
19 | public ProtoClient(CountDownLatch networkStarter) {
20 | this.network = new Network();
21 | network.start(networkStarter);
22 | }
23 |
24 | public static void main(String[] args) throws Exception {
25 | CountDownLatch networkStarter = new CountDownLatch(1);
26 | ProtoClient protoClient = new ProtoClient(networkStarter);
27 |
28 | protoClient.run(Paths.get("demo.txt"));
29 | }
30 |
31 | public void run(Path path) throws IOException {
32 | sendFile(path, future -> {
33 | if (!future.isSuccess()) {
34 | future.cause().printStackTrace();
35 | network.stop();
36 | }
37 | if (future.isSuccess()) {
38 | System.out.println("Файл успешно передан");
39 | network.stop();
40 | }
41 | });
42 | }
43 |
44 | private void sendFile(Path path, ChannelFutureListener finishListener) throws IOException {
45 | Channel channel = network.getCurrentChannel();
46 |
47 | FileRegion region = new DefaultFileRegion(path.toFile(), 0, Files.size(path));
48 |
49 | ByteBuf buf;
50 | buf = ByteBufAllocator.DEFAULT.directBuffer(1);
51 | buf.writeByte(MAGIC_BYTE);
52 | network.getCurrentChannel().writeAndFlush(buf);
53 |
54 | byte[] filenameBytes = path.getFileName().toString().getBytes(StandardCharsets.UTF_8);
55 | buf = ByteBufAllocator.DEFAULT.directBuffer(Integer.SIZE / Byte.SIZE);
56 | buf.writeInt(filenameBytes.length);
57 | channel.writeAndFlush(buf);
58 |
59 | buf = ByteBufAllocator.DEFAULT.directBuffer(filenameBytes.length);
60 | buf.writeBytes(filenameBytes);
61 | channel.writeAndFlush(buf);
62 |
63 | buf = ByteBufAllocator.DEFAULT.directBuffer(Long.SIZE / Byte.SIZE);
64 | buf.writeLong(Files.size(path));
65 | channel.writeAndFlush(buf);
66 |
67 | ChannelFuture transferOperationFuture = channel.writeAndFlush(region);
68 | if (finishListener != null) {
69 | transferOperationFuture.addListener(finishListener);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/proto/old/Network.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.proto.old;
2 |
3 | import io.netty.bootstrap.Bootstrap;
4 | import io.netty.channel.Channel;
5 | import io.netty.channel.ChannelFuture;
6 | import io.netty.channel.ChannelInitializer;
7 | import io.netty.channel.EventLoopGroup;
8 | import io.netty.channel.nio.NioEventLoopGroup;
9 | import io.netty.channel.socket.SocketChannel;
10 | import io.netty.channel.socket.nio.NioSocketChannel;
11 |
12 | import java.net.InetSocketAddress;
13 | import java.util.concurrent.CountDownLatch;
14 |
15 | public final class Network {
16 | private static final Network NETWORK = new Network();
17 | public static final int PORT = 8189;
18 |
19 | public static Network getInstance() {
20 | return NETWORK;
21 | }
22 |
23 | private Network() {
24 | }
25 |
26 | private Channel currentChannel;
27 |
28 | public Channel getCurrentChannel() {
29 | return currentChannel;
30 | }
31 |
32 | public void start(CountDownLatch countDownLatch) {
33 | EventLoopGroup group = new NioEventLoopGroup();
34 | try {
35 | Bootstrap clientBootstrap = new Bootstrap();
36 | clientBootstrap.group(group)
37 | .channel(NioSocketChannel.class)
38 | .remoteAddress(new InetSocketAddress("localhost", PORT))
39 | .handler(new ChannelInitializer() {
40 | protected void initChannel(SocketChannel socketChannel) throws Exception {
41 | socketChannel.pipeline().addLast();
42 | currentChannel = socketChannel;
43 | }
44 | });
45 | ChannelFuture channelFuture = clientBootstrap.connect().sync();
46 | countDownLatch.countDown();
47 | channelFuture.channel().closeFuture().sync();
48 | } catch (Exception e) {
49 | e.printStackTrace();
50 | } finally {
51 | try {
52 | group.shutdownGracefully().sync();
53 | } catch (InterruptedException e) {
54 | e.printStackTrace();
55 | }
56 | }
57 | }
58 |
59 | public void stop() {
60 | currentChannel.close();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/proto/old/ProtoClient.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.proto.old;
2 |
3 | import java.nio.file.Paths;
4 | import java.util.concurrent.CountDownLatch;
5 |
6 | public class ProtoClient {
7 | public static void main(String[] args) throws Exception {
8 | CountDownLatch networkStarter = new CountDownLatch(1);
9 | new Thread(() -> Network.getInstance().start(networkStarter)).start();
10 | networkStarter.await();
11 |
12 | ProtoFileSender.sendFile(Paths.get("demo.txt"), Network.getInstance().getCurrentChannel(), future -> {
13 | if (!future.isSuccess()) {
14 | future.cause().printStackTrace();
15 | // Network.getInstance().stop();
16 | }
17 | if (future.isSuccess()) {
18 | System.out.println("Файл успешно передан");
19 | // Network.getInstance().stop();
20 | }
21 | });
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/proto/old/ProtoFileSender.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.proto.old;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.buffer.ByteBufAllocator;
5 | import io.netty.channel.*;
6 |
7 | import java.io.IOException;
8 | import java.nio.charset.StandardCharsets;
9 | import java.nio.file.Files;
10 | import java.nio.file.Path;
11 |
12 | public final class ProtoFileSender {
13 |
14 | private ProtoFileSender() {
15 | }
16 |
17 | public static final byte MAGIC_BYTE = (byte) 25;
18 |
19 | public static void sendFile(Path path, Channel channel, ChannelFutureListener finishListener) throws IOException {
20 | FileRegion region = new DefaultFileRegion(path.toFile(), 0, Files.size(path));
21 |
22 | ByteBuf buf;
23 | buf = ByteBufAllocator.DEFAULT.directBuffer(1);
24 | buf.writeByte(MAGIC_BYTE);
25 | channel.writeAndFlush(buf);
26 |
27 | byte[] filenameBytes = path.getFileName().toString().getBytes(StandardCharsets.UTF_8);
28 | buf = ByteBufAllocator.DEFAULT.directBuffer(Integer.SIZE / Byte.SIZE);
29 | buf.writeInt(filenameBytes.length);
30 | channel.writeAndFlush(buf);
31 |
32 | buf = ByteBufAllocator.DEFAULT.directBuffer(filenameBytes.length);
33 | buf.writeBytes(filenameBytes);
34 | channel.writeAndFlush(buf);
35 |
36 | buf = ByteBufAllocator.DEFAULT.directBuffer(Long.SIZE / Byte.SIZE);
37 | buf.writeLong(Files.size(path));
38 | channel.writeAndFlush(buf);
39 |
40 | ChannelFuture transferOperationFuture = channel.writeAndFlush(region);
41 | if (finishListener != null) {
42 | transferOperationFuture.addListener(finishListener);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/proto/server/ProtoHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.proto.server;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 |
7 | import java.io.BufferedOutputStream;
8 | import java.io.FileOutputStream;
9 |
10 | public class ProtoHandler extends ChannelInboundHandlerAdapter {
11 |
12 | public static final byte MAGIC_BYTE = (byte) 25;
13 | private State currentState = State.IDLE;
14 | private int nextLength;
15 | private long fileLength;
16 | private long receivedFileLength;
17 | private BufferedOutputStream out;
18 |
19 |
20 | // byte - команда
21 | // filename_size: int - длина имени файла
22 | // byte[filename_size] - имя файла
23 | // file_size: long - размер файла
24 | // byte[file_size] - контент файла
25 | @Override
26 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
27 | ByteBuf buf = ((ByteBuf) msg);
28 | while (buf.readableBytes() > 0) {
29 | if (currentState == State.IDLE) {
30 | byte readed = buf.readByte();
31 | if (readed == MAGIC_BYTE) {
32 | currentState = State.NAME_LENGTH;
33 | receivedFileLength = 0L;
34 | System.out.println("STATE: Start file receiving");
35 | } else {
36 | System.out.println("ERROR: Invalid first byte - " + readed);
37 | }
38 | }
39 |
40 |
41 | if (currentState == State.NAME_LENGTH) {
42 | if (buf.readableBytes() >= (Integer.SIZE / Byte.SIZE)) {
43 | System.out.println("STATE: Get filename length");
44 | nextLength = buf.readInt();
45 | currentState = State.NAME;
46 | }
47 | }
48 |
49 | if (currentState == State.NAME) {
50 | if (buf.readableBytes() >= nextLength) {
51 | byte[] fileName = new byte[nextLength];
52 | buf.readBytes(fileName);
53 | System.out.println("STATE: Filename received - _" + new String(fileName, "UTF-8"));
54 | out = new BufferedOutputStream(new FileOutputStream("_" + new String(fileName)));
55 | currentState = State.FILE_LENGTH;
56 | }
57 | }
58 |
59 | if (currentState == State.FILE_LENGTH) {
60 | if (buf.readableBytes() >= (Long.SIZE / Byte.SIZE)) {
61 | fileLength = buf.readLong();
62 | System.out.println("STATE: File length received - " + fileLength);
63 | currentState = State.FILE;
64 | }
65 | }
66 |
67 | if (currentState == State.FILE) {
68 | while (buf.readableBytes() > 0) {
69 | out.write(buf.readByte());
70 | receivedFileLength++;
71 | if (fileLength == receivedFileLength) {
72 | currentState = State.IDLE;
73 | System.out.println("File received");
74 | out.close();
75 | break;
76 | }
77 | }
78 | }
79 | }
80 | if (buf.readableBytes() == 0) {
81 | buf.release();
82 | }
83 | }
84 |
85 | @Override
86 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
87 | cause.printStackTrace();
88 | ctx.close();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/proto/server/ProtoServer.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.proto.server;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.EventLoopGroup;
7 | import io.netty.channel.nio.NioEventLoopGroup;
8 | import io.netty.channel.socket.SocketChannel;
9 | import io.netty.channel.socket.nio.NioServerSocketChannel;
10 |
11 | public class ProtoServer {
12 |
13 | public static final int INET_PORT = 8189;
14 |
15 | public void run() throws Exception {
16 | EventLoopGroup bossGroup = new NioEventLoopGroup();
17 | EventLoopGroup workerGroup = new NioEventLoopGroup();
18 | try {
19 | ServerBootstrap b = new ServerBootstrap();
20 | b.group(bossGroup, workerGroup)
21 | .channel(NioServerSocketChannel.class)
22 | .childHandler(new ChannelInitializer() {
23 | @Override
24 | public void initChannel(SocketChannel ch) {
25 | ch.pipeline().addLast(new ProtoHandler());
26 | }
27 | });
28 | ChannelFuture f = b.bind(INET_PORT).sync();
29 | f.channel().closeFuture().sync();
30 | } finally {
31 | workerGroup.shutdownGracefully();
32 | bossGroup.shutdownGracefully();
33 | }
34 | }
35 |
36 | public static void main(String[] args) throws Exception {
37 | new ProtoServer().run();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/proto/server/State.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.proto.server;
2 |
3 | public enum State {
4 | IDLE,
5 | NAME_LENGTH,
6 | NAME,
7 | FILE_LENGTH,
8 | FILE
9 | }
10 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/serialization/Client.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.serialization;
2 |
3 | import io.netty.handler.codec.serialization.ObjectDecoderInputStream;
4 | import io.netty.handler.codec.serialization.ObjectEncoderOutputStream;
5 | import ru.daniilazarnov.serialization.domain.MyMessage;
6 |
7 | import java.net.Socket;
8 |
9 | public class Client {
10 |
11 | public static final int PORT = 8189;
12 | public static final int MAX_OBJECT_SIZE = 100 * 1024 * 1024;
13 |
14 | public static void main(String[] args) {
15 |
16 | try (Socket socket = new Socket("localhost", PORT);
17 | ObjectEncoderOutputStream oeos = new ObjectEncoderOutputStream(socket.getOutputStream());
18 | ObjectDecoderInputStream odis = new ObjectDecoderInputStream(socket.getInputStream(), MAX_OBJECT_SIZE)) {
19 | MyMessage textMessage = new MyMessage("Hello Server!!!");
20 |
21 | oeos.writeObject(textMessage);
22 | oeos.flush();
23 | MyMessage msgFromServer = (MyMessage) odis.readObject();
24 | System.out.println("Answer from server: " + msgFromServer.getText());
25 | } catch (Exception e) {
26 | e.printStackTrace();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/serialization/CloudServer.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.serialization;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.EventLoopGroup;
7 | import io.netty.channel.nio.NioEventLoopGroup;
8 | import io.netty.channel.socket.SocketChannel;
9 | import io.netty.channel.socket.nio.NioServerSocketChannel;
10 | import io.netty.handler.codec.serialization.ClassResolvers;
11 | import io.netty.handler.codec.serialization.ObjectDecoder;
12 | import io.netty.handler.codec.serialization.ObjectEncoder;
13 |
14 | public class CloudServer {
15 |
16 | public static final int MAX_OBJECT_SIZE = 1024 * 1024 * 100;
17 | public static final int INET_PORT = 8189;
18 |
19 | public void run() throws Exception {
20 | EventLoopGroup mainGroup = new NioEventLoopGroup();
21 | EventLoopGroup workerGroup = new NioEventLoopGroup();
22 | try {
23 | ServerBootstrap b = new ServerBootstrap();
24 | b.group(mainGroup, workerGroup)
25 | .channel(NioServerSocketChannel.class)
26 | .childHandler(new ChannelInitializer() {
27 | protected void initChannel(SocketChannel socketChannel) throws Exception {
28 | socketChannel.pipeline().addLast(
29 | new ObjectDecoder(MAX_OBJECT_SIZE, ClassResolvers.cacheDisabled(null)),
30 | new ObjectEncoder(),
31 | new CloudServerHandler()
32 | );
33 | }
34 | });
35 | ChannelFuture future = b.bind(INET_PORT).sync();
36 | future.channel().closeFuture().sync();
37 | } finally {
38 | mainGroup.shutdownGracefully();
39 | workerGroup.shutdownGracefully();
40 | }
41 | }
42 |
43 | public static void main(String[] args) throws Exception {
44 | new CloudServer().run();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/serialization/CloudServerHandler.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.serialization;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 | import ru.daniilazarnov.serialization.domain.FileMessage;
6 | import ru.daniilazarnov.serialization.domain.MyMessage;
7 |
8 | import java.io.IOException;
9 | import java.nio.file.Files;
10 | import java.nio.file.Path;
11 | import java.nio.file.StandardOpenOption;
12 |
13 | public class CloudServerHandler extends ChannelInboundHandlerAdapter {
14 |
15 | @Override
16 | public void channelActive(ChannelHandlerContext ctx) {
17 | System.out.println("Client connected...");
18 | }
19 |
20 | @Override
21 | public void channelInactive(ChannelHandlerContext ctx) {
22 | System.out.println("Client disconnected...");
23 | }
24 |
25 | @Override
26 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
27 | System.out.println(msg.getClass().getName());
28 | if (msg instanceof MyMessage) {
29 | System.out.println("Client text message: " + ((MyMessage) msg).getText());
30 | ctx.writeAndFlush(new MyMessage("Hello Client!"));
31 | }
32 | if (msg instanceof FileMessage) {
33 | System.out.println("save file..");
34 | ctx.writeAndFlush(new MyMessage("Your file was succsefuly save"));
35 | try {
36 | Path path = Path.of(((FileMessage) msg).getFileName());
37 | Files.write(path, ((FileMessage) msg).getContent(), StandardOpenOption.CREATE_NEW);
38 | } catch (IOException e) {
39 | e.printStackTrace();
40 | }
41 | } else {
42 | System.out.printf("Server received wrong object!");
43 | }
44 | }
45 |
46 | @Override
47 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
48 | cause.printStackTrace();
49 | ctx.close();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/serialization/domain/FileMessage.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.serialization.domain;
2 |
3 | import java.io.Serializable;
4 |
5 | public class FileMessage implements Serializable {
6 |
7 | private final String fileName;
8 | private final byte[] content;
9 |
10 | public FileMessage(String fileName, byte[] content) {
11 | this.fileName = fileName;
12 | this.content = content;
13 | }
14 |
15 | public String getFileName() {
16 | return fileName;
17 | }
18 |
19 | public byte[] getContent() {
20 | return content;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lesson-3/src/main/java/ru/daniilazarnov/serialization/domain/MyMessage.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov.serialization.domain;
2 |
3 | import java.io.Serializable;
4 |
5 | public class MyMessage implements Serializable {
6 |
7 | private static final long serialVersionUID = 5193392663743561680L;
8 |
9 | private final String text;
10 |
11 | public MyMessage(String text) {
12 | this.text = text;
13 | }
14 |
15 | public String getText() {
16 | return text;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lesson-3/src/main/resources/Netty_Idea_Diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/azarnovdaniil/java-net-course/3f8a3f4c3abf95fa060aafb6593a850f3945cad3/lesson-3/src/main/resources/Netty_Idea_Diagram.png
--------------------------------------------------------------------------------
/lesson-4/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | java-net-course
7 | ru.daniilazarnov
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | lesson-4
13 |
14 |
15 | 11
16 | 11
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lesson-4/src/main/java/ru/daniilazarnov/Main.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov;
2 |
3 | public class Main {
4 |
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/lesson-4/src/test/java/ru/daniilazarnov/LambdaTest.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.util.Comparator;
6 | import java.util.List;
7 | import java.util.SortedSet;
8 | import java.util.TreeSet;
9 | import java.util.function.*;
10 |
11 | class LambdaTest {
12 |
13 | @Test
14 | void testRunnableBeforeJava8() {
15 | Runnable runnable = new Runnable() {
16 | @Override
17 | public void run() {
18 | System.out.println("I am Runnable from java 7!");
19 | }
20 | };
21 |
22 | runnable.run();
23 | }
24 |
25 | @Test
26 | void testRunnableAfterJava8() {
27 | Runnable runnable = () -> {
28 | System.out.println("I am Runnable from java 8!");
29 | };
30 |
31 | runnable.run();
32 | }
33 |
34 | @FunctionalInterface
35 | interface MyLambda {
36 | String apply(String s1, String s2);
37 | }
38 |
39 | @Test
40 | void testMyLambda() {
41 |
42 | class Person {
43 |
44 | private final String firstName;
45 | private final String lasName;
46 |
47 | public Person(String firstName, String lasName) {
48 | this.firstName = firstName;
49 | this.lasName = lasName;
50 | }
51 |
52 | public String getInfo(MyLambda myLambda) {
53 | return myLambda.apply(firstName, lasName);
54 | }
55 |
56 | public String getTsv() {
57 | return firstName + "\t" + lasName;
58 | }
59 |
60 | public String getCsv() {
61 | return firstName + "," + lasName;
62 | }
63 | }
64 |
65 | Person person = new Person("Vasya", "Pupkin");
66 |
67 | String csv = person.getInfo((f, l) -> f + "," + l);
68 | System.out.println(csv);
69 |
70 | String tsv = person.getInfo((f, l) -> f + "\t" + l);
71 | System.out.println(tsv);
72 | }
73 |
74 |
75 | @Test
76 | void testFinalOrEffectivelyFinal() {
77 |
78 | int i = 0;
79 |
80 | int[] ints = new int[1];
81 | ints[0]++;
82 |
83 | Function function = str -> {
84 | String end = "Number: ";
85 | return str + " - " + end + i + ints[0];
86 | };
87 |
88 | String s = function.apply("Ivan");
89 |
90 | System.out.println(s);
91 | }
92 |
93 | @Test
94 | void testConsumer() {
95 | Consumer consumer = s -> System.out.println("Print from consumer: " + s);
96 |
97 | consumer.accept("Vasya");
98 | }
99 |
100 | @Test
101 | void testSupplier() {
102 | Supplier supplier = () -> "";
103 |
104 | System.out.println(supplier.get());
105 | }
106 |
107 | @Test
108 | void testFunction() {
109 | Function function = str -> str + "1";
110 |
111 | System.out.println(function.apply("Maria"));
112 | }
113 |
114 | @Test
115 | void testPredicate() {
116 | Predicate predicate = s -> {
117 | return s.isEmpty();
118 | };
119 |
120 | System.out.println(predicate.test(""));
121 | System.out.println(predicate.test("not empty"));
122 | }
123 |
124 | @Test
125 | void testMethodReference1() {
126 | List.of("1", "2", "3").forEach(System.out::println);
127 |
128 | int[] i = new int[]{0};
129 | i[0] = 1;
130 |
131 | methodReferenceWithTwo((var1, var2) -> System.out.println(var1.length() + 100 + var2 + i[0]));
132 | }
133 |
134 | @Test
135 | void testMethodReference2() {
136 | methodReferenceWithTwo(LambdaTest::printStringPlusInteger);
137 |
138 | SortedSet set = new TreeSet<>(Comparator.comparingInt(String::length));
139 | }
140 |
141 | static void printStringPlusInteger(String firstName, String lastName) {
142 | System.out.println(firstName + "," + lastName);
143 | }
144 |
145 | static void methodReferenceWithTwo(BiConsumer biConsumer) {
146 | biConsumer.accept("Ivan", "Fedorov");
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/lesson-4/src/test/java/ru/daniilazarnov/StreamTest.java:
--------------------------------------------------------------------------------
1 | package ru.daniilazarnov;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.io.IOException;
6 | import java.nio.charset.StandardCharsets;
7 | import java.nio.file.Files;
8 | import java.nio.file.Path;
9 | import java.util.*;
10 | import java.util.function.Function;
11 | import java.util.stream.Collectors;
12 | import java.util.stream.Stream;
13 |
14 | import static org.junit.jupiter.api.Assertions.assertThrows;
15 |
16 | class StreamTest {
17 |
18 | @Test
19 | void testForI() {
20 | int[] ints = new int[10];
21 | for (int i = 0; i < ints.length; i++) {
22 | System.out.println(ints[i]);
23 | }
24 |
25 | while (true) {
26 | break;
27 | }
28 |
29 | do {
30 | break;
31 | } while (true);
32 | }
33 |
34 | @Test
35 | void testFor() {
36 | int[] ints = new int[10];
37 |
38 | for (int anInt : ints) {
39 | System.out.println(anInt);
40 | }
41 |
42 | class MyIterable implements Iterable {
43 |
44 | @Override
45 | public Iterator iterator() {
46 | return new Iterator() {
47 | @Override
48 | public boolean hasNext() {
49 | return false;
50 | }
51 |
52 | @Override
53 | public String next() {
54 | return "";
55 | }
56 | };
57 | }
58 | }
59 |
60 | MyIterable myIterable = new MyIterable();
61 |
62 | for (String s : myIterable) {
63 | System.out.println(s);
64 | }
65 | }
66 |
67 | @Test
68 | void testIterator() {
69 | List strings = List.of("aa", "bb", "cc");
70 |
71 | Iterator iterator = strings.iterator();
72 | while (iterator.hasNext()) {
73 | System.out.println(iterator.next());
74 | }
75 | }
76 |
77 | @Test
78 | void testSpliterator() {
79 | List strings = List.of("aa", "bb", "cc");
80 |
81 | Spliterator spliterator = strings.spliterator();
82 | spliterator.forEachRemaining(s -> System.out.println(s));
83 | }
84 |
85 | @Test
86 | void testStream0() {
87 |
88 | class Person {
89 |
90 | private final String firstName;
91 | private final String lasName;
92 |
93 | public Person(String firstName, String lasName) {
94 | this.firstName = firstName;
95 | this.lasName = lasName;
96 | }
97 |
98 | @Override
99 | public String toString() {
100 | return "Person{" +
101 | "firstName='" + firstName + '\'' +
102 | ", lasName='" + lasName + '\'' +
103 | '}';
104 | }
105 | }
106 |
107 | List persons = List.of(
108 | new Person("Ivan", "Fedorov"),
109 | new Person("Daniil", "Azarnov"),
110 | new Person("Mike", "Petrov"),
111 | new Person("Alex", "Bashirov")
112 | );
113 |
114 |
115 | List firstLetterAInLastName = new ArrayList<>();
116 | int counter = 0;
117 | for (int i = 0; i < persons.size(); i++) {
118 | Person person = persons.get(i);
119 | if (person.lasName.charAt(0) == 'A') {
120 | int length = person.lasName.length();
121 | counter += length;
122 | }
123 | }
124 |
125 | System.out.println(counter);
126 |
127 | System.out.println(firstLetterAInLastName);
128 |
129 | final int count = persons.stream()
130 | .filter(person -> person.lasName.charAt(0) == 'A')
131 | .map(person -> person.lasName.length())
132 | .mapToInt(Integer::intValue)
133 | .sum();
134 |
135 | System.out.println(count);
136 | }
137 |
138 | @Test
139 | void testStream() {
140 | List strings = List.of("aa", "bb", "cc");
141 |
142 | strings.stream()
143 | .map(str -> str + "-map1")
144 | .map(s -> s + "-map2")
145 | .forEach(System.out::println);
146 |
147 | System.out.println(strings);
148 |
149 | // Stream stringStream = strings.stream()
150 | // .map(s -> s + "dd")
151 | // .map(s -> s + " map2")
152 | // .peek(System.out::println);
153 | //
154 | // System.out.println();
155 | //
156 | // stringStream.forEach(System.out::println);
157 | //
158 | // System.out.println(strings);
159 | //
160 | // System.out.println();
161 | }
162 |
163 | @Test
164 | void testTerminalOperation() {
165 | List strings = List.of("aa", "bb", "cc");
166 |
167 | Stream stringStream = strings.stream()
168 | .map(str -> str + "-map1")
169 | .peek(s -> System.out.println("Peek: " + s))
170 | .map(s -> s + "-map2");
171 |
172 | stringStream.forEach(System.out::println);
173 |
174 | assertThrows(IllegalStateException.class, () -> stringStream.forEach(System.out::println));
175 | }
176 |
177 | @Test
178 | void testReuseStream() {
179 | Stream stream = List.of("1", "2", "3").stream();
180 |
181 | stream.map(Integer::valueOf).map(x -> x + 1).forEach(System.out::println);
182 |
183 | assertThrows(IllegalStateException.class, () -> stream.forEach(System.out::println));
184 | }
185 |
186 | @Test
187 | void testStreamSimpleStream() {
188 | List strings = List.of("aa", "bb", "cc");
189 |
190 | class SimpleStream {
191 | private final Iterable iterable;
192 | private Function mapper;
193 |
194 | public SimpleStream(Iterable iterable) {
195 | this.iterable = iterable;
196 | }
197 |
198 | /**
199 | * Lazy operation
200 | */
201 | SimpleStream map(Function mapper) {
202 | this.mapper = mapper;
203 | return this;
204 | }
205 |
206 | /**
207 | * Terminal operation
208 | */
209 | void print() {
210 | Iterator iterator = iterable.iterator();
211 | while (iterator.hasNext()) {
212 | System.out.println(mapper.apply(iterator.next()));
213 | }
214 | }
215 | }
216 |
217 | SimpleStream simpleStream = new SimpleStream(strings);
218 | simpleStream.map(s -> s + "dd").print();
219 | }
220 |
221 | @Test
222 | void testMap() {
223 | List strings = List.of("aa", "bb", "cc");
224 |
225 | strings.stream()
226 | .map(s -> s + "dd")
227 | .forEach(s -> System.out.println(s));
228 | }
229 |
230 | @Test
231 | void testMap1() {
232 | List strings = List.of("aa", "bb", "cc");
233 | strings.stream()
234 | .map(s -> s + "dd")
235 | .map(s -> s + " ii")
236 | .map(s -> s.getBytes(StandardCharsets.UTF_8))
237 | .map(bytes -> bytes.length)
238 | .map(integer -> integer + 1)
239 | .mapToInt(Integer::intValue)
240 | .forEach(System.out::println);
241 | }
242 |
243 | @Test
244 | void testReduce0() {
245 | List strings = List.of("aa", "bb", "cc");
246 |
247 | System.out.println(strings.stream()
248 | .map(s -> s.length())
249 | .reduce((s, s2) -> s + s2).get());
250 | }
251 |
252 | @Test
253 | void testReduce() {
254 | List strings = List.of("aa", "bb", "cc");
255 |
256 | String reduce = strings.stream()
257 | // FIRST + aa -> FIRSTaa + bb -> aabb + cc -> aabbcc
258 | .reduce("FIRST", (s, s2) -> {
259 | System.out.println(s);
260 | System.out.println(s2);
261 | String result = s + s2;
262 | System.out.println(result);
263 | System.out.println();
264 | return result;
265 | });
266 |
267 | System.out.println(strings);
268 | System.out.println(reduce);
269 |
270 | List empty = List.of();
271 | Optional optionalReduce = empty.stream()
272 | .reduce((s, s2) -> s + s2);
273 |
274 | List booleans = List.of(true, false, true, false);
275 | Optional reduce1 = booleans.stream().reduce((aBoolean, aBoolean2) -> aBoolean || aBoolean2);
276 | System.out.println(reduce1.get());
277 |
278 | System.out.println(optionalReduce.orElse("DEFAULT"));
279 | }
280 |
281 | class MyOptional {
282 |
283 | R value;
284 |
285 | public MyOptional(R value) {
286 | this.value = value;
287 | }
288 |
289 | R get() {
290 | return value;
291 | }
292 |
293 | R orElse(R defaultValue) {
294 | if (value == null) {
295 | return defaultValue;
296 | }
297 | return value;
298 | }
299 | }
300 |
301 | @Test
302 | void testSize() {
303 | List strings = List.of("aa", "bb", "cc");
304 |
305 |
306 | int size = strings.stream()
307 | .map(s -> 1)
308 | .reduce((integer, integer2) -> integer + integer2)
309 | .get();
310 |
311 | System.out.println(size);
312 |
313 | int size1 = strings.size();
314 | System.out.println(size1);
315 |
316 | Integer reduce = strings.stream()
317 | .map(s -> 1)
318 | .reduce(0, Integer::sum);
319 |
320 | int sum = List.of(1, 2, 3, 4)
321 | .stream()
322 | .reduce(0, Integer::sum);
323 |
324 | System.out.println(List.of("aa", "aaa", "aa")
325 | .stream()
326 | .map(String::length)
327 | .map(x -> x >= 2)
328 | .reduce(true, (b1, b2) -> b1 && b2)
329 | .booleanValue());
330 |
331 | System.out.println("aresxdghftjgymhujhkvjghmfcngmv".chars()
332 | .map(x -> x == 'a' ? 1 : 0)
333 | .sum());
334 |
335 | //System.out.println(reduce);
336 | }
337 |
338 | @Test
339 | void testFilter() {
340 | List strings = List.of("aa", "bb", "cc");
341 |
342 | strings.stream()
343 | .peek(s -> System.out.println("Before filter: " + s))
344 | .filter(s -> s.equals("aa"))
345 | .forEach(s -> System.out.println("After filter: " + s));
346 |
347 | strings.stream().map(s -> {
348 | if (s.equals("aa")) {
349 | return s;
350 | } else {
351 | return "";
352 | }
353 | }).forEach(System.out::println);
354 |
355 | }
356 |
357 | @Test
358 | void testMatch() {
359 | List strings = List.of("aa", "bb", "cc");
360 |
361 | boolean allMatch = strings.stream()
362 | .allMatch(s -> s.equals("aa"));
363 |
364 | System.out.println(allMatch);
365 |
366 | boolean anyMatch = strings.stream()
367 | .anyMatch(s -> s.equals("aa"));
368 |
369 | System.out.println(anyMatch);
370 |
371 | boolean allMatchReduce = strings.stream()
372 | // aa -> true, bb -> false, cc -> false
373 | .map(s -> s.equals("aa"))
374 | // true && false -> false + false -> false
375 | .reduce((aBoolean, aBoolean2) -> aBoolean && aBoolean2)
376 | .orElse(false);
377 |
378 | System.out.println(allMatchReduce);
379 |
380 | boolean anyMatchReduce = strings.stream()
381 | .map(s -> s.equals("aa"))
382 | .reduce(false, (aBoolean, aBoolean2) -> aBoolean || aBoolean2);
383 |
384 | System.out.println(anyMatchReduce);
385 |
386 | System.out.println(strings);
387 | }
388 |
389 | @Test
390 | void testSorted() {
391 | List integers = List.of(1, 3, 4, 2);
392 |
393 | integers.stream()
394 | .sorted()
395 | .forEach(System.out::println);
396 |
397 | System.out.println(List.of("Cотников", "Цоцонова", "Фоменков")
398 | .stream()
399 | .sorted(Comparator.comparingInt(s -> s.charAt(0)))
400 | .findFirst()
401 | .orElse("Азарнов"));
402 | }
403 |
404 | @Test
405 | void testStreamStudent() {
406 | List.of(new Student("Ivan", "Petrov", 1),
407 | new Student("Fedor", "Smirnov", 2),
408 | new Student("Fedot", "Matveev", 3)
409 | ).stream()
410 | .filter(student -> student.getCourse() >= 2)
411 | .forEach(System.out::println);
412 | }
413 |
414 | class Student {
415 | private final String firstName;
416 | private final String lastName;
417 | private final int course;
418 |
419 | public Student(String firstName, String lastName, int course) {
420 | this.firstName = firstName;
421 | this.lastName = lastName;
422 | this.course = course;
423 | }
424 |
425 | public String getFirstName() {
426 | return firstName;
427 | }
428 |
429 | public String getLastName() {
430 | return lastName;
431 | }
432 |
433 | public int getCourse() {
434 | return course;
435 | }
436 |
437 | @Override
438 | public String toString() {
439 | return "Student{" +
440 | "firstName='" + firstName + '\'' +
441 | ", lastName='" + lastName + '\'' +
442 | ", course=" + course +
443 | '}';
444 | }
445 | }
446 |
447 | @Test
448 | void testCollect() {
449 | List strings = List.of("aa", "bb", "cc");
450 |
451 | ArrayList