Skip to content
This repository has been archived by the owner on Sep 9, 2021. It is now read-only.

Шаляпин Георгий, 3530901/70201 #37

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .github/pull_request_template.md

This file was deleted.

140 changes: 49 additions & 91 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,49 @@
# Лабораторные работы за осенний семестр 2020

В `master` ветке данного репозитория присутствуют актуальные задания, включая
распределение протоколов по студентам.

# Прогресс

Легенда:

| Символ | Значение |
| -- | -- |
| | Работа не сдана или находится на рассмотрении |
| + | Работа принята |
| ! | Работа рассмотрена, требуется демо |
| ? | Работа рассмотрена, но требует доработки |
| - | Работу сдавать не требуется |
| -------- | -------- |
| SSH ключ | [Отправить SSH ключ преподавателю](https://insysnw.github.io/labs/900-ssh-keygen/) |
| Л.1a | [TCP чат](https://insysnw.github.io/labs/01-tcp-chat/) |
| Л.1б | [TCP чат](https://insysnw.github.io/labs/01-tcp-chat/) (неблокирующие сокеты) |
| Л.2c | [UDP сервер существующего протокола](https://insysnw.github.io/labs/02-udp-real-protocol/) |
| Л.2к | [UDP клиент существующего протокола](https://insysnw.github.io/labs/02-udp-real-protocol/) |
| Л.3с | Сервер для задания из методички (пункт 1.2.`n`) |
| Л.3к | Клиент для задания из методички (пункт 1.2.`n`) |

## Группа 201

| ФИО | SSH ключ | Л.1a | Л.1б | Л.2c | Л.2к | Л.3 |
| -- | -- | -- | -- | -- | -- | -- |
| Антропова А.А. | + | | | | | |
| Белов Е.А. | + | [?](../../pull/10) | | tftp | dhcp | |
| Буй К.Д. | + | | | tftp | dns | |
| Гладкова Е.Д. | + | | | | | |
| Голзицкий Н.С. | + | | | | | |
| Гуляев Д.В. | | | | | | |
| Данилов А.И. | + | [?](../../pull/8) | | dhcp | ntp | |
| Казанджи М.А. | + | [?](../../pull/7) | [?](../../pull/7) | ntp | snmp | |
| Киселев Н.Д. | + | | | dns | tftp | |
| Лялин А.С. | + | | | | | |
| Натура А.А. | + | | | snmp | dns | |
| Никитин И.Н. | + | | | | | |
| Романов А.Л. | + | | | dns | dhcp | |
| Свечников Р.А. | + | [?](../../pull/6) | | dhcp | dns | |
| Сибагатулин А.Ф. | | | | | | |
| Товпеко К.А. | + | [?](../../pull/2) | [?](../../pull/2) | dns | ntp | |
| Черноног С.А. | + | | | | | |
| Шаляпин Г.А. | + | | | | | |

## Группа 203

| ФИО | Ssh ключ | Л.1a | Л.1б | Л.2с | Л.2к | Л.3с | Л.3к |
| -- | -- | -- | -- | -- | -- | -- | -- |
| Ворошилов А.А. | + | | | | | | |
| Гусев Н.С. | | | | | | | |
| Зарецкая Е.С. | | | | ntp | tftp | 17 | 18 |
| Иванов И.Д. | + | | [+](../../pull/13) | dns | ntp | 8 | 5 |
| Калашников Р.А. | | | | dns | snmp | | |
| Костарев В.И. | + | | | dhcp | snmp | | |
| Любченкова А.А. | + | | | tftp | dns | 18 | 17 |
| Меньшов П.А. | + | | | dns | tftp | | |
| Морозов Е.С. | + | | | dns | dhcp | | |
| Никитина Д.С. | + | | | | | | |
| Овсянников Е.А. | + | [?](../../pull/11) | | tftp | ntp | | |
| Орлова П.А. | + | | | tftp | dns | | |
| Пентегов А.О. | + | | | | | | |
| Семёнов Д.С. | + | | | dhcp | dns | 19 | 7 |
| Середин К.В. | + | [?](../../pull/5) | | dhcp | ntp | 7 | 19 |
| Трушин И.А. | + | | | tftp | dhcp | | |
| Черникова А.С. | + | | | tftp | ntp | 5 | 8 |
| Шелепов В.А. | + | | | dhcp | tftp | | |

# Требования к отчету:

* Инструкция по использованию;
* Инструкция по сборке/установке;
* Описание используемого протокола;
* Своего для первой и третьей лабораторной;
* Используемого подмножества для второй;
* ???
* PROFIT

Отчет можно писать как в сообщении к PR-у, так и присылать в иных
форматах (`.pdf`, `.docx`, `.txt` и т.п.).

# Порядок сдачи

* Fork от данного репозитория
* Push каждой лабораторной в отдельную ветку
* Создание отдельного PR на каждую лабораторную

При создании PR, в качестве напоминалки, сделан шаблон.
# Лабораторная работа № 1

Работа выполнена на языке Kotlin (версия Kotlin 1.4.20, версия Java 15.0.1).
Сборка производится с помощью Gradle (версия 6.5.1)

# Описание
При создании клиента необходимо ввести имя. Оно должно быть уникальным и не содержать символов `[` и `]`.
Чтобы завершить работу, необходимо ввести `!q`.
Помимо обычных сообщений передаются также служебные уведомления о подключении или отключении пользователей.

# Использование
Названия jar-файлов (здесь и в дальнейшем без расширения):

| Тип сокетов | Сервер | Клиент |
| ------------- |------------- | ------------- |
| блокирующие | `bserver` | `bclient` |
| неблокирующие | `nbserver` | `nbclient` |

## Сборка
Сборка всех jar-файлов:
```
gradle all
```
Сборка конкретного файла:
```
gradle (name)
```

## Запуск
```
java -jar (name).jar [ip [port]]
```

# Протокол
Каждое сообщение наследует класс `Message`. Возможные типы сообщений:

| Тип | Описание | Поля
| --- | --- | ---
| `ConnectionRequest` | клиент подключается к серверу | `username`
| `ConnectionResponse` | сервер рассылает всем уведомления о новом клиенте | `username`, `date`
| `ConnectionDenied` | отказ клиенту в подключении из-за неуникального ника | `username`
| `DisconnectionRequest` | клиент отключается от сервера | `username`
| `DisconnectionResponse` | сервер рассылает всем уведомления об отключении клиента |`username`, `date`
| `UserMessage` | сообщение клиента |`username`, `message`, `date`

Поля:
* `username`: ник пользователя
* `date`: время прихода сообщения на сервер
* `message`: сообщение
38 changes: 38 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
val jarTasks = mapOf(
"bclient" to "blocking.Client",
"bserver" to "blocking.Server",
"nbclient" to "non_blocking.Client",
"nbserver" to "non_blocking.Server"
)

plugins {
id("org.jetbrains.kotlin.jvm") version "1.4.20"
}

repositories {
jcenter()
}

sourceSets["main"].java { srcDir("src") }

tasks.withType<Jar> {
destinationDirectory.set(rootDir)
}

for (taskMainClass in jarTasks) {
tasks.register<Jar>(taskMainClass.key) {
from(sourceSets["main"].output) {
manifest {
attributes["Main-Class"] = taskMainClass.value
}
archiveFileName.set("${taskMainClass.key}.jar")
from(configurations.compileClasspath.map { config ->
config.map { if (it.isDirectory) it else zipTree(it) }
})
}
}
}

tasks.register<Jar>("all") {
dependsOn(jarTasks.keys)
}
118 changes: 118 additions & 0 deletions src/blocking/Client.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package blocking

import common.*
import java.io.IOException
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.net.Socket
import kotlin.system.exitProcess

class Client(addr: String, port: Int) {
private var socket: Socket
private lateinit var socketInput: ObjectInputStream
private lateinit var socketOutput: ObjectOutputStream
private var username: String? = null

init {
try {
socket = Socket(addr, port)
} catch (e: IOException) {
System.err.println(Strings.SOCKET_NOT_CREATED)
exitProcess(-1)
}
try {
socketInput = ObjectInputStream(socket.getInputStream())
socketOutput = ObjectOutputStream(socket.getOutputStream())

enterUsername()
readThread().start()
writeThread().start()
} catch (e: IOException) {
shutdown(Status.EXCEPTION)
}
}

private fun ObjectOutputStream.writeAndFlush(obj: Any) {
writeObject(obj)
flush()
}

private fun enterUsername() {
print(Strings.ENTER_USERNAME)
while (username == null) {
try {
var userInput = readLine()
while (userInput != null && userInput.contains(Regex("""[\[\]]"""))) {
System.err.print(Strings.BAD_USERNAME)
userInput = readLine()
}

socketOutput.writeAndFlush(ConnectionRequest(userInput!!))

when (socketInput.readObject()) {
is ConnectionResponse -> {
username = userInput
println(Strings.HELLO(username))
}
is ConnectionDenied -> {
System.err.print(Strings.TAKEN_USERNAME)
}
}
} catch (e: IOException) {
shutdown(Status.EXCEPTION)
}
}
}

private fun shutdown(status: Status) {
try {
if (!socket.isClosed) {
socketInput.close()
socketOutput.close()
socket.close()
}
} catch (e: IOException) {
}
println(status.message)
exitProcess(status.code)
}

private fun readThread() = Thread {
try {
while (!socket.isClosed) {
println(socketInput.readObject())
}
} catch (e: IOException) {
shutdown(Status.EXCEPTION)
}
}

private fun writeThread() = Thread {
try {
while (!socket.isClosed) {
val userInput = readLine()
if (userInput == STOP_WORD || userInput == null) {
socketOutput.writeAndFlush(DisconnectionRequest(username!!))
shutdown(Status.OK)
break
} else {
socketOutput.writeAndFlush(UserMessage(username!!, userInput))
}
}
} catch (e: IOException) {
shutdown(Status.EXCEPTION)
}
}

companion object {
@JvmStatic
fun main(args: Array<String>) {
when {
args.size >= 2 -> Client(args[0], args[1].toIntOrNull() ?: DEFAULT_PORT)
args.size == 1 -> Client(args[0], DEFAULT_PORT)
else -> Client(DEFAULT_ADDRESS, DEFAULT_PORT)
}
}
}
}

Loading