先存个档

main
lensfrex 2 years ago
commit 3fc7f6131a
Signed by: lensfrex
GPG Key ID: 947ADABD8533C476
  1. 33
      .gitignore
  2. 20
      exp1-oop/pom.xml
  3. 30
      exp1-oop/src/main/java/net/lensfrex/AbstractExtends.java
  4. 26
      exp1-oop/src/main/java/net/lensfrex/Interface.java
  5. 51
      exp1-oop/src/main/java/net/lensfrex/Main.java
  6. 33
      exp1-oop/src/main/java/net/lensfrex/Rectangle.java
  7. 20
      exp2-thread/pom.xml
  8. 42
      exp2-thread/src/main/java/net/lensfrex/Main.java
  9. 42
      exp2-thread/src/main/java/net/lensfrex/RabbitAndTortoise.java
  10. 40
      exp2-thread/src/main/java/net/lensfrex/Ticket.java
  11. 39
      exp3-network/pom.xml
  12. 53
      exp3-network/src/main/java/net/lensfrex/Main.java
  13. 44
      exp3-network/src/main/java/net/lensfrex/URLConnectionResource.java
  14. 216
      exp3-network/src/main/java/net/lensfrex/socket/client/Client.java
  15. 4
      exp3-network/src/main/java/net/lensfrex/socket/client/Global.java
  16. 7
      exp3-network/src/main/java/net/lensfrex/socket/client/MainUI.java
  17. 34
      exp3-network/src/main/java/net/lensfrex/socket/client/controller/ClientConnection.java
  18. 44
      exp3-network/src/main/java/net/lensfrex/socket/common/Common.java
  19. 16
      exp3-network/src/main/java/net/lensfrex/socket/common/Constant.java
  20. 60
      exp3-network/src/main/java/net/lensfrex/socket/common/DataPack.java
  21. 80
      exp3-network/src/main/java/net/lensfrex/socket/common/MessageData.java
  22. 36
      exp3-network/src/main/java/net/lensfrex/socket/common/User.java
  23. 66
      exp3-network/src/main/java/net/lensfrex/socket/common/Util.java
  24. 118
      exp3-network/src/main/java/net/lensfrex/socket/server/Server.java
  25. 23
      pom.xml
  26. 7
      src/main/java/net/lensfrex/Main.java

33
.gitignore vendored

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.lensfrex</groupId>
<artifactId>lesson</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>exp1-oop</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,30 @@
package net.lensfrex;
public class AbstractExtends {
protected void run() {
Father father = new Child();
father.method1();
father.method2();
}
}
// ------------------------------------------
abstract class Father {
public abstract void method1();
public abstract void method2();
}
// -------------------------------------------
class Child extends Father {
@Override
public void method1() {
System.out.println("Do some thing in method1");
}
@Override
public void method2() {
System.out.println("Do some thing in method2");
}
}

@ -0,0 +1,26 @@
package net.lensfrex;
public class Interface {
protected void run() {
AnInterface anInterface = new AnInterface() {
@Override
public void method1() {
System.out.println("Do some thing in method1");
}
@Override
public void method2() {
System.out.println("Do some thing in method2");
}
};
anInterface.method1();
anInterface.method2();
}
}
interface AnInterface {
void method1();
void method2();
}

@ -0,0 +1,51 @@
package net.lensfrex;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws Exception {
if (args.length > 0) {
execute(args[0]);
} else {
System.out.println("Witch to run? (1, 2, 3)");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
execute(reader.readLine());
}
}
private static void execute(String option) {
Main main = new Main();
switch (option) {
case "1":
main.run1();
break;
case "2":
main.run2();
break;
case "3":
main.run3();
break;
default:
System.out.printf("Invalid input for '%s'%n", option);
}
}
private void run1() {
Rectangle rectangle = new Rectangle(3, 4);
System.out.println("rectangleHeight: " + rectangle.getHeight());
System.out.println("rectangleWidth: " + rectangle.getWidth());
System.out.println("rectangleSize: " + rectangle.getSize());
}
private void run2() {
new Interface().run();
}
private void run3() {
new AbstractExtends().run();
}
}

@ -0,0 +1,33 @@
package net.lensfrex;
public class Rectangle {
private float height = 0;
private float width = 0;
public Rectangle() {}
public Rectangle(float height, float width) {
this.height = height;
this.width = width;
}
public float getSize() {
return height * width;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
}

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.lensfrex</groupId>
<artifactId>lesson</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>exp2-thread</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,42 @@
package net.lensfrex;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("Thread Lesson report");
if (args.length > 0) {
execute(args[0]);
} else {
System.out.println("Witch to run? (1, 2)");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
execute(reader.readLine());
}
}
private static void execute(String option) {
Main main = new Main();
switch (option) {
case "1":
main.run1();
break;
case "2":
main.run2();
break;
default:
System.out.printf("Invalid input for '%s'%n", option);
}
}
private void run1() {
new RabbitAndTortoise().runTest();
}
private void run2() {
new Ticket().runTest();
}
}

@ -0,0 +1,42 @@
package net.lensfrex;
public class RabbitAndTortoise {
public void runTest() {
Animal rabbit = new Animal("Rabbit", 16, 32);
Animal tortoise = new Animal("Tortoise", 8, 32);
new Thread(rabbit).start();
new Thread(tortoise).start();
}
}
class Animal implements Runnable {
private final String name;
private final int speed;
private final int targetDistance;
private int totalDistance = 0;
public Animal(String name, int speed, int targetDistance) {
this.name = name;
this.speed = speed;
this.targetDistance = targetDistance;
}
@Override
public void run() {
while (totalDistance <= targetDistance) {
try {
Thread.sleep((int) (Math.random() * 1000) + 500);
} catch (Exception ignored) {
return;
}
totalDistance += speed;
System.out.printf("[%s] has run %d%n", name, totalDistance);
}
System.out.printf("[%s] has finish the game.%n", name);
}
}

@ -0,0 +1,40 @@
package net.lensfrex;
public class Ticket {
public void runTest() {
TicketOffice ticketOffice = new TicketOffice();
new Thread(ticketOffice, "0").start();
new Thread(ticketOffice, "1").start();
new Thread(ticketOffice, "2").start();
}
}
class TicketOffice implements Runnable {
private static int ticket = 8;
@Override
public void run() {
String name = Thread.currentThread().getName();
while(sellTicket(name));
}
private boolean sellTicket(String name) {
synchronized (this) {
if (ticket <= 0) {
System.out.printf("[%s]: Ticket was sold out.%n", name);
return false;
}
System.out.printf("TicketOffice '%s' is selling ticket No.%s%n", name, ticket);
ticket--;
try {
Thread.sleep(128);
} catch (Exception ignored) {
return false;
}
}
return true;
}
}

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.lensfrex</groupId>
<artifactId>lesson</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>exp3-network</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,53 @@
package net.lensfrex;
import net.lensfrex.socket.client.Client;
import net.lensfrex.socket.server.Server;
import net.lensfrex.socket.common.Util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("Thread Lesson report");
if (args.length > 0) {
execute(args[0]);
} else {
System.out.println("Witch to run? (1server, 1client, 2)");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
execute(reader.readLine());
}
}
private static void execute(String option) {
Main main = new Main();
switch (option) {
case "1server":
main.run1Server();
break;
case "1client":
main.run1Client();
break;
case "2":
main.run2();
break;
default:
System.out.printf("Invalid input for '%s'%n", option);
}
}
private void run1Server() {
new Server().start();
}
private void run1Client() {
new Client().start();
}
private void run2() {
new URLConnectionResource().startTest();
}
}

@ -0,0 +1,44 @@
package net.lensfrex;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class URLConnectionResource {
private static final String targetSite = "https://www.gnu.org/licenses/gpl-3.0.txt";
public void startTest() {
URLConnection urlConnection;
try {
urlConnection = new URL(targetSite).openConnection();
Set<Map.Entry<String, List<String>>> headers = urlConnection.getHeaderFields().entrySet();
for (Map.Entry<String, List<String>> entry : headers) {
String key = entry.getKey();
List<String> values = entry.getValue();
for (String value : values) {
System.out.printf("%s: %s%n", key, value);
}
}
} catch (Exception e) {
e.printStackTrace();
return;
}
System.err.println("--------------------------------");
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), StandardCharsets.UTF_8))) {
String line = bufferedReader.readLine();
for (int i = 0; line != null && i < 10; i++, line = bufferedReader.readLine()) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

@ -0,0 +1,216 @@
package net.lensfrex.socket.client;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import net.lensfrex.socket.client.controller.ClientConnection;
import net.lensfrex.socket.common.Common;
import net.lensfrex.socket.common.Constant;
import net.lensfrex.socket.common.DataPack;
import net.lensfrex.socket.common.MessageData;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Random;
public class Client extends Application {
public void start() {
launch();
}
@Override
public void start(Stage stage) throws Exception {
Scene scene = new Scene(new UI().buildUI(), 515, 509);
// 主题,不想要或者网络出错的话注释掉就好了
// scene.getStylesheets().add(new URL("https://www.lensfrex.net/light.css").toExternalForm());
// scene.getStylesheets().add(new URL("https://www.lensfrex.net/dark.css").toExternalForm());
scene.getStylesheets().add(new URL("http://127.0.0.1/light.css").toExternalForm());
stage.setTitle("( ̄﹃ ̄)");
stage.setScene(scene);
stage.show();
}
}
class UI {
private static final String[] DEFAULT_USERNAMES = {"Rex", "Red", "Ash", "Aether"};
private Pane pane;
private VBox rootBox;
private HBox serverControlVBox;
private TextField serverTextField;
private TextArea messageTextArea;
private HBox userControlVBox;
private TextField usernameTextField;
private Button loginButton, logoutButton;
private HBox messageControlVBox;
private TextField messageTextField;
private Button sendButton;
protected Parent buildUI() {
pane = new Pane();
rootBox = new VBox();
rootBox.setPadding(new Insets(10, 10, 10, 10));
rootBox.setSpacing(20);
rootBox.setPrefWidth(500);
rootBox.setPrefHeight(500);
messageTextArea = new TextArea("暂无消息...");
messageTextArea.setPrefHeight(700);
messageTextArea.setEditable(false);
rootBox.getChildren().addAll(serverControlPane(), userControlPane(), messageTextArea, messageControlPane());
pane.getChildren().addAll(rootBox);
return pane;
}
private HBox serverControlPane() {
serverControlVBox = new HBox();
serverControlVBox.setSpacing(10);
serverControlVBox.setAlignment(Pos.CENTER_LEFT);
Label serverLabel = new Label("服务器地址:");
serverTextField = new TextField("127.0.0.1:2333");
serverTextField.setPrefWidth(320);
serverControlVBox.getChildren().addAll(serverLabel, serverTextField);
return serverControlVBox;
}
private HBox userControlPane() {
userControlVBox = new HBox();
userControlVBox.setSpacing(10);
userControlVBox.setAlignment(Pos.CENTER_LEFT);
Label usernameLabel = new Label("用户名:");
String username = DEFAULT_USERNAMES[new Random().nextInt(DEFAULT_USERNAMES.length)];
usernameTextField = new TextField(username);
usernameTextField.setPrefWidth(200);
loginButton = new Button("登录");
loginButton.setOnAction(e -> {
try {
this.auth(Constant.OPCODE_LOGIN);
logoutButton.setDisable(false);
loginButton.setDisable(true);
serverTextField.setDisable(true);
usernameTextField.setDisable(true);
messageControlVBox.setDisable(false);
} catch (Exception ex) {
ex.printStackTrace();
messageTextArea.textProperty().set("登录服务器时发生错误:" + ex);
}
});
logoutButton = new Button("注销");
logoutButton.setDisable(true);
logoutButton.setOnAction(e -> {
try {
this.auth(Constant.OPCODE_LOGOUT);
logoutButton.setDisable(true);
loginButton.setDisable(false);
serverTextField.setDisable(false);
usernameTextField.setDisable(false);
messageControlVBox.setDisable(true);
} catch (Exception ex) {
ex.printStackTrace();
messageTextArea.textProperty().set("登录服务器时发生错误:" + ex);
}
});
userControlVBox.getChildren().addAll(usernameLabel, usernameTextField, loginButton, logoutButton);
return userControlVBox;
}
private void auth(byte[] opcode) throws Exception {
String[] address = serverTextField.getText().split(":");
int port = Integer.parseInt(address[1]);
ClientConnection connection = new ClientConnection(address[0], port);
byte[] data = usernameTextField.getText().getBytes(StandardCharsets.UTF_8);
OutputStream outputStream = connection.getOutputStream();
Common.send(data, opcode, outputStream);
connection.finishOutput();
InputStream inputStream = connection.getInputStream();
byte[] header = new byte[4];
inputStream.read(header);
DataPack dataPack = Common.readDataPack(inputStream);
MessageData messageData = MessageData.parse(dataPack.getData());
messageTextArea.textProperty().set(messageTextArea.getText() +
String.format("\n服务器[%s]响应:%s", messageData.getIdText(), messageData.getMessageText()));
connection.finishInput();
connection.disconnect();
}
private HBox messageControlPane() {
messageControlVBox = new HBox();
messageControlVBox.setSpacing(10);
messageControlVBox.setAlignment(Pos.CENTER_LEFT);
messageControlVBox.setDisable(true);
Label usernameLabel = new Label("输入消息:");
messageTextField = new TextField();
messageTextField.setPrefWidth(320);
sendButton = new Button("发送");
sendButton.setOnAction(e -> {
String[] address = serverTextField.getText().split(":");
int port = Integer.parseInt(address[1]);
try {
ClientConnection connection = new ClientConnection(address[0], port);
MessageData messageData = new MessageData(usernameTextField.getText(), messageTextField.getText());
Common.send(messageData.toBytes(), Constant.OPCODE_SEND_MESSAGE, connection.getOutputStream());
connection.finishOutput();
InputStream inputStream = connection.getInputStream();
byte[] header = new byte[4];
inputStream.read(header);
DataPack dataPack = Common.readDataPack(inputStream);
MessageData responseData = MessageData.parse(dataPack.getData());
messageTextArea.textProperty().set(messageTextArea.getText() +
String.format("\n服务器[%s]响应:%s", responseData.getIdText(), responseData.getMessageText()));
connection.finishInput();
connection.disconnect();
} catch (IOException ex) {
ex.printStackTrace();
messageTextArea.textProperty().set("登录服务器时发生错误:" + ex);
}
});
messageControlVBox.getChildren().addAll(usernameLabel, messageTextField, sendButton);
return messageControlVBox;
}
}

@ -0,0 +1,4 @@
package net.lensfrex.socket.client;
public class Global {
}

@ -0,0 +1,7 @@
package net.lensfrex.socket.client;
import javafx.scene.layout.Pane;
public class MainUI extends Pane {
}

@ -0,0 +1,34 @@
package net.lensfrex.socket.client.controller;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientConnection {
private final Socket socket;
public ClientConnection(String host, int port) throws IOException {
this.socket = new Socket(host, port);
}
public InputStream getInputStream() throws IOException {
return socket.getInputStream();
}
public OutputStream getOutputStream() throws IOException {
return socket.getOutputStream();
}
public void disconnect() throws IOException {
socket.close();
}
public void finishOutput() throws IOException {
socket.shutdownOutput();
}
public void finishInput() throws IOException {
socket.shutdownInput();
}
}

@ -0,0 +1,44 @@
package net.lensfrex.socket.common;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
public class Common {
public static DataPack readDataPack(InputStream inputStream) {
return readDataPack(Util.readAllData(inputStream));
}
public static DataPack readDataPack(byte[] dataPackBytes) {
return DataPack.parse(dataPackBytes);
}
public static int sendMessage(String id, String message, OutputStream outputStream) throws IOException {
MessageData messageData = new MessageData(id, message);
return sendMessage(messageData, outputStream);
}
public static int sendMessage(MessageData message, OutputStream outputStream) throws IOException {
return sendMessage(message.toBytes(), outputStream);
}
public static int sendMessage(byte[] data, OutputStream outputStream) throws IOException {
return send(data, Constant.OPCODE_SEND_MESSAGE, outputStream);
}
public static int send(byte[] data, byte[] opcode, OutputStream outputStream) throws IOException {
DataPack dataPack = new DataPack(opcode, data);
return send(dataPack, outputStream);
}
public static int send(DataPack dataPack, OutputStream outputStream) throws IOException {
outputStream.write(Constant.MAGIC_HEADER);
outputStream.write(dataPack.toBytes());
outputStream.flush();
return dataPack.getDataLength();
}
}

@ -0,0 +1,16 @@
package net.lensfrex.socket.common;
import java.nio.charset.StandardCharsets;
public class Constant {
public static final int LENGTH_BYTE_SIZE = 4;
public static final byte[] MAGIC_HEADER = "AETH".getBytes(StandardCharsets.UTF_8);
public static final int OPCODE_LENGTH = 4;
public static final byte[] OPCODE_REQUEST_MESSAGE = "RMSG".getBytes(StandardCharsets.UTF_8);
public static final byte[] OPCODE_SEND_MESSAGE = "SMSG".getBytes(StandardCharsets.UTF_8);
public static final byte[] OPCODE_LOGIN = "LOGI".getBytes(StandardCharsets.UTF_8);
public static final byte[] OPCODE_LOGOUT = "LOGO".getBytes(StandardCharsets.UTF_8);
public static final String MESSAGE_OK = "OPERATION-OK";
}

@ -0,0 +1,60 @@
package net.lensfrex.socket.common;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.util.Arrays;
public class DataPack implements Serializable {
private final byte[] opcode;
private final byte[] data;
public DataPack(byte[] opcode, byte[] data) {
this.opcode = opcode;
this.data = data;
}
public static DataPack parse(byte[] bytes) {
int offset = 0;
byte[] opcode = Arrays.copyOfRange(bytes, offset, offset + Constant.OPCODE_LENGTH);
offset += Constant.OPCODE_LENGTH;
int dataLength = Util.bytesToInt32(Arrays.copyOfRange(bytes, offset, offset + Constant.LENGTH_BYTE_SIZE));
offset += Constant.LENGTH_BYTE_SIZE;
byte[] data = Arrays.copyOfRange(bytes, offset, offset + dataLength);
return new DataPack(opcode, data);
}
public byte[] toBytes() {
try {
int totalLength = Constant.OPCODE_LENGTH + Constant.LENGTH_BYTE_SIZE + data.length;
ByteArrayOutputStream stream = new ByteArrayOutputStream(totalLength);
stream.write(opcode);
stream.write(Util.int32ToBytes(data.length));
stream.write(data);
return stream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public byte[] getOpcode() {
return opcode;
}
public byte[] getData() {
return data;
}
public int getTotalLength() {
return Constant.OPCODE_LENGTH + Constant.LENGTH_BYTE_SIZE + data.length;
}
public int getDataLength() {
return data.length;
}
}

@ -0,0 +1,80 @@
package net.lensfrex.socket.common;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class MessageData implements Serializable {
private final byte[] id;
private final byte[] messageData;
public MessageData(byte[] id, byte[] messageData) {
this.id = id;
this.messageData = messageData;
}
public MessageData(String id, String messageData) {
this.id = id.getBytes(StandardCharsets.UTF_8);
this.messageData = messageData.getBytes(StandardCharsets.UTF_8);
}
public static MessageData parse(byte[] data) {
int offset = 0;
int idLength = Util.bytesToInt32(Arrays.copyOfRange(data, offset, offset + Constant.LENGTH_BYTE_SIZE));
offset += Constant.LENGTH_BYTE_SIZE;
byte[] id = Arrays.copyOfRange(data, offset, offset + idLength);
offset += idLength;
int messageDataLength = Util.bytesToInt32(Arrays.copyOfRange(data, offset, offset + Constant.LENGTH_BYTE_SIZE));
offset += Constant.LENGTH_BYTE_SIZE;
byte[] messageData = Arrays.copyOfRange(data, offset, offset + messageDataLength);
return new MessageData(id, messageData);
}
public byte[] toBytes() {
try {
int byteSize = Constant.LENGTH_BYTE_SIZE * 2 + id.length + messageData.length;
ByteArrayOutputStream stream = new ByteArrayOutputStream(byteSize);
stream.write(Util.int32ToBytes(id.length));
stream.write(id);
stream.write(Util.int32ToBytes(messageData.length));
stream.write(messageData);
return stream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public byte[] getId() {
return id;
}
public String getIdText() {
return new String(id);
}
public byte[] getMessageData() {
return messageData;
}
public String getMessageText() {
return new String(messageData);
}
@Override
public String toString() {
return "MessageData{" +
"idLength=" + id.length +
", id='" + new String(id) +
"', messageLength=" + messageData.length +
", messageData='" + new String(messageData) +
";}";
}
}

@ -0,0 +1,36 @@
package net.lensfrex.socket.common;
import java.util.Objects;
public class User {
private final String id;
public User(String id) {
this.id = id;
}
public User(byte[] id) {
this.id = new String(id);
}
public String getId() {
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id.equals(user.id);
}
public boolean equals(String id) {
return this.id.equals(id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}

@ -0,0 +1,66 @@
package net.lensfrex.socket.common;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
public class Util {
private static final char[] alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
private static final Random random = new Random();
public static String randomString(int length) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append(alphabet[random.nextInt(alphabet.length)]);
}
return sb.toString();
}
public static int bytesToInt32(byte[] bytes) {
int result = 0;
for (int i = 0; i < 4; i++) {
int shift = (3 - i) * 8;
result += (bytes[i] & 0xFF) << shift;
}
return result;
}
public static byte[] int32ToBytes(int i) {
byte[] result = new byte[4];
result[0] = (byte) ((i >> 24) & 0xFF);
result[1] = (byte) ((i >> 16) & 0xFF);
result[2] = (byte) ((i >> 8) & 0xFF);
result[3] = (byte) (i & 0xFF);
return result;
}
public static byte[] readAllData(InputStream inputStream) {
return readAllData(inputStream, 5);// read every 5kb in default
}
public static byte[] readAllData(InputStream inputStream, int byteAllocation) {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[1024 * byteAllocation];
while(true) {
int length = inputStream.read(bytes);
if (length == -1) {
break;
}
byteArrayOutputStream.write(bytes, 0, length);
}
byteArrayOutputStream.flush();
return byteArrayOutputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

@ -0,0 +1,118 @@
package net.lensfrex.socket.server;
import net.lensfrex.socket.common.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.HashSet;
public class Server {
private static boolean stop = false;
public void start() {
Server.stop = false;
try (ServerSocket serverSocket = new ServerSocket(2333)) {
while (!stop) {
// Start a new thread to service more than one client
new ServerThread(serverSocket.accept()).start();
}
} catch (Exception e) {
System.err.println("Some exception happened: " + e);
}
}
public void stop() {
Server.stop = true;
}
}
class ServerThread extends Thread {
private static final String SERVER_ID = "MASTER-SERVER";
private static final HashSet<User> onlineUsers = new HashSet<>();
private final Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream()) {
byte[] clientMagicHeader = new byte[Constant.MAGIC_HEADER.length];
if (inputStream.read(clientMagicHeader) == -1) {
return;
}
this.executeAction(inputStream, outputStream);
socket.shutdownOutput();
socket.shutdownInput();
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void executeAction(InputStream inputStream, OutputStream outputStream) throws IOException {
DataPack dataPack = Common.readDataPack(inputStream);
byte[] opcode = dataPack.getOpcode();
if (Arrays.equals(Constant.OPCODE_LOGIN, opcode)) {
this.login(new String(dataPack.getData()));
Common.sendMessage(SERVER_ID, Constant.MESSAGE_OK, outputStream);
} else if (Arrays.equals(Constant.OPCODE_LOGOUT, opcode)) {
this.logout(new String(dataPack.getData()));
Common.sendMessage(SERVER_ID, Constant.MESSAGE_OK, outputStream);
} else if (Arrays.equals(Constant.OPCODE_REQUEST_MESSAGE, opcode)) {
this.sendRandomMessage(outputStream);
} else if (Arrays.equals(Constant.OPCODE_SEND_MESSAGE, opcode)) {
String receivedMessage = this.receiveMessage(dataPack);
String responseMessage = String.format("Receive message '%s'", receivedMessage);
Common.sendMessage(SERVER_ID, responseMessage, outputStream);
}
}
private void login(String id) {
onlineUsers.add(new User(id));
System.out.printf("User '%s' login.%n", id);
}
private void logout(String id) {
onlineUsers.remove(new User(id));
System.out.printf("User '%s' logout.%n", id);
}
private void sendRandomMessage(OutputStream outputStream) throws IOException {
this.sendMessage(Util.randomString(64), outputStream);
}
private void sendMessage(String messageText, OutputStream outputStream) throws IOException {
Common.sendMessage(SERVER_ID, messageText, outputStream);
}
private String receiveMessage(DataPack dataPack) {
byte[] data = dataPack.getData();
MessageData messageData = MessageData.parse(data);
User user = new User(messageData.getIdText());
if (!onlineUsers.contains(user)) {
String message = "User " + user.getId() + " is not online, but send a message.";
System.err.println(message);
return message;
}
System.out.printf("Receive message '%s' from: '%s'%n", messageData.getMessageText(), user.getId());
System.out.println("----------------");
return messageData.getMessageText();
}
}

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.lensfrex</groupId>
<artifactId>lesson</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>exp1-oop</module>
<module>exp2-thread</module>
<module>exp3-network</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,7 @@
package net.lensfrex;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
Loading…
Cancel
Save