-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from vlasival/task_2_1_2
task_2_1_2
- Loading branch information
Showing
20 changed files
with
1,323 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# | ||
# https://help.github.com/articles/dealing-with-line-endings/ | ||
# | ||
# Linux start script should use lf | ||
/gradlew text eol=lf | ||
|
||
# These are Windows script files and should use crlf | ||
*.bat text eol=crlf | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Ignore Gradle project-specific cache directory | ||
.gradle | ||
|
||
# Ignore Gradle build output directory | ||
build | ||
|
||
bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* This file was generated by the Gradle 'init' task. | ||
* | ||
* This generated file contains a sample Java application project to get you started. | ||
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.6/userguide/building_java_projects.html in the Gradle documentation. | ||
*/ | ||
|
||
plugins { | ||
// Apply the application plugin to add support for building a CLI application in Java. | ||
id 'application' | ||
id 'jacoco' | ||
} | ||
|
||
repositories { | ||
// Use Maven Central for resolving dependencies. | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
// Use JUnit Jupiter for testing. | ||
testImplementation libs.junit.jupiter | ||
|
||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||
|
||
// This dependency is used by the application. | ||
implementation libs.guava | ||
|
||
compileOnly 'org.projectlombok:lombok:1.18.32' | ||
annotationProcessor 'org.projectlombok:lombok:1.18.32' | ||
|
||
testCompileOnly 'org.projectlombok:lombok:1.18.32' | ||
testAnnotationProcessor 'org.projectlombok:lombok:1.18.32' | ||
} | ||
|
||
// Apply a specific Java toolchain to ease working on different environments. | ||
java { | ||
toolchain { | ||
languageVersion = JavaLanguageVersion.of(21) | ||
} | ||
} | ||
|
||
application { | ||
// Define the main class for the application. | ||
mainClass = 'org.example.App' | ||
} | ||
|
||
tasks.named('test') { | ||
// Use JUnit Platform for unit tests. | ||
useJUnitPlatform() | ||
} | ||
|
||
jacocoTestReport { | ||
reports { | ||
xml.required = true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.prime; | ||
|
||
import java.io.Serializable; | ||
import java.util.List; | ||
import lombok.Data; | ||
|
||
/** | ||
* Class represents a message wandering on the network. | ||
*/ | ||
@Data | ||
public class Message implements Serializable { | ||
private String type; | ||
private List<Integer> data; | ||
} |
183 changes: 183 additions & 0 deletions
183
task_2_1_2/app/src/main/java/org/prime/PrimeClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
package org.prime; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.ObjectInputStream; | ||
import java.io.ObjectOutputStream; | ||
import java.net.InetSocketAddress; | ||
import java.nio.ByteBuffer; | ||
import java.nio.channels.SocketChannel; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
/** | ||
* PrimeClient class that implements a client for distributed checking of numbers for primality. | ||
*/ | ||
public class PrimeClient { | ||
|
||
private SocketChannel socket; | ||
private ByteBuffer buffer; | ||
|
||
/** | ||
* PrimeClient constructor. | ||
* | ||
* @param address server address | ||
* @param port server port | ||
*/ | ||
public PrimeClient(String address, int port) { | ||
try { | ||
socket = SocketChannel.open(new InetSocketAddress(address, port)); | ||
socket.configureBlocking(false); | ||
buffer = ByteBuffer.allocate(PrimeUtils.BUFFER_SIZE); | ||
System.out.println("Channel bound and configured on IP \'" + address | ||
+ "\' and port " + port); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
System.out.println("Failed to bind socket"); | ||
} | ||
} | ||
|
||
/** | ||
* Client launch. | ||
* | ||
* @throws IOException if an I/O error occurs | ||
*/ | ||
public void start() throws IOException { | ||
sendMessage(createMessage("REQUEST", null)); | ||
int requestAttempts = 0; | ||
|
||
while (true) { | ||
buffer.clear(); | ||
int bytesRead = socket.read(buffer); | ||
if (bytesRead == -1) { | ||
System.out.println("Server is down. Shutting down..."); | ||
return; | ||
} | ||
if (bytesRead > 0) { | ||
buffer.flip(); | ||
try { | ||
Message message = readMessageFromBuffer(); | ||
String messageType = message.getType(); | ||
switch (messageType) { | ||
case "TASK": | ||
handleTask(message.getData()); | ||
requestAttempts = 0; | ||
break; | ||
case "EXIT": | ||
System.out.println("Tasks done. Exiting program..."); | ||
return; | ||
default: | ||
System.out.println("Unknown message type. Synchronize types."); | ||
break; | ||
} | ||
} catch (ClassNotFoundException e) { | ||
if (requestAttempts >= 3) { | ||
System.out.println("Too many attempts to receive message. Aborting..."); | ||
return; | ||
} | ||
System.out.println("Error casting received message to Message class."); | ||
sendMessage(createMessage("REQUEST", null)); | ||
requestAttempts++; | ||
} | ||
buffer.clear(); | ||
} | ||
|
||
// Sleep for a short duration to prevent busy-waiting | ||
try { | ||
Thread.sleep(1); | ||
} catch (InterruptedException e) { | ||
System.out.println("Client thread interrupted. Exiting..."); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Creating a message to send in network. | ||
* | ||
* @param type message type | ||
* @param data message data | ||
* @return message | ||
*/ | ||
private Message createMessage(String type, List<Integer> data) { | ||
Message message = new Message(); | ||
message.setType(type); | ||
message.setData(data); | ||
return message; | ||
} | ||
|
||
/** | ||
* Sending message to the server method. | ||
* | ||
* @param message message to send | ||
* @throws IOException if an I/O error occurs | ||
*/ | ||
private void sendMessage(Message message) throws IOException { | ||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); | ||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); | ||
objectOutputStream.writeObject(message); | ||
objectOutputStream.flush(); | ||
byte[] data = byteArrayOutputStream.toByteArray(); | ||
ByteBuffer buffer = ByteBuffer.wrap(data); | ||
socket.write(buffer); | ||
} | ||
|
||
/** | ||
* Read a message from client buffer. | ||
* | ||
* @return readed message | ||
* @throws IOException if an I/O error occurs | ||
* @throws ClassNotFoundException if class of buffer data don't cast to message class | ||
*/ | ||
private Message readMessageFromBuffer() throws IOException, ClassNotFoundException { | ||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buffer.array()); | ||
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); | ||
return (Message) objectInputStream.readObject(); | ||
} | ||
|
||
/** | ||
* List primality checking. | ||
* | ||
* @param nums list of numbers to check | ||
* @throws IOException if an I/O error occurs | ||
*/ | ||
private void handleTask(List<Integer> nums) throws IOException { | ||
for (Integer number : nums) { | ||
if (!isPrime(number)) { | ||
sendMessage(createMessage("RESULT", null)); | ||
return; | ||
} | ||
} | ||
sendMessage(createMessage("RESULT", new ArrayList<>())); | ||
} | ||
|
||
/** | ||
* Number primality checking. | ||
* | ||
* @param number number to check | ||
* @return true if prime, false otherwise | ||
*/ | ||
public boolean isPrime(int number) { | ||
if (number <= 1) { | ||
return false; | ||
} | ||
for (int i = 2; i <= Math.sqrt(number); i++) { | ||
if (number % i == 0) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
/** | ||
* Entry point to start a client. | ||
* | ||
* @param args command line args | ||
* @throws IOException if an I/O error occurs | ||
*/ | ||
public static void main(String[] args) throws IOException { | ||
PrimeClient client = new PrimeClient("localhost", 5000); | ||
client.start(); | ||
} | ||
} |
Oops, something went wrong.