Ударная аутентификация порта Java UDP. Множество клиентов одновременно

Это мой студенческий проект. Я получил 4/5 баллов, но подозреваю, что там много странностей. У меня никогда не было возможности услышать отзыв своего учителя об этом, и это меня беспокоит, поэтому я подумал, что кто-то может взглянуть на него и дать отзыв.

Быстрая документация

Сначала мы запускаем программу «Сервер», которая открывает порты, предоставленные аргументами среды выполнения.[] параметры прослушивания параллельно в отдельных потоках.
Затем мы запускаем «Клиент», передавая имя хоста конструктора и список портов, которые нужно сбить. Мы можем запустить много клиентов или установить переменную numberofclients в коде.

Серверные UDP-сокеты имеют доступ к синхронизированной структуре данных, в которой хранится информация о входящих соединениях с сокетами.
После каждого подключения программа проверяет, соответствует ли порядок подключений ключевому. Если да затем сервер отправляет сообщение с TCP-портом в сокет неавторизованного, но все же клиента, который отправил правильную комбинацию портов, и другой поток запускается с TCP-сокетом, который прослушивает авторизованного клиента. Авторизованный клиент подключается к TCP-сокету и обменивается короткой информацией с сервером. После обмена TCP сокет закрывается.

Клавиша Enter закрывает программу, и все потоки и сокеты освобождаются.

Сервер

package com.company;

import java.io.IOException;
import java.net.*;
import java.util.*;
import java.util.stream.Collectors;

public class Server implements Runnable{
    byte[] buffer = new byte[2048];
    byte[] sendBuffer = new byte[2048];

    List<DatagramSocket> socketList;
    Map<InetSocketAddress, List<Integer>> internalMap;
    Map<InetSocketAddress, List<Integer>> guestMap;
    List<Integer> key;

    Server(Integer... ports) throws SocketException {
        this.key = new ArrayList<>();
        //key.addAll(Arrays.asList(ports));
        for(Integer portnumber : ports)
            key.add(portnumber);

        this.socketList = new ArrayList<>();
        this.internalMap = new HashMap<>();
        this.guestMap = Collections.synchronizedMap(internalMap);

        List<Integer> uniquePorts = key.stream().distinct().collect(Collectors.toList());

        for(Integer port: uniquePorts){
            DatagramSocket socket = new DatagramSocket(port);
            socketList.add(socket);
        }

        System.out.println("Zajete porty: ");
        socketList.forEach(n -> System.out.print(n.getLocalPort() + ", "));
        System.out.println();


        this.key = socketList.stream().map(DatagramSocket::getLocalPort).collect(Collectors.toList());
    }


    @Override
    public void run() {

        for(DatagramSocket socket : socketList){
            Thread t = new Thread(){
                boolean running;
                @Override
                public void run() {

                    while(true){
                        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

                        try {
                            socket.receive(packet);
                            ProtocolMessage msgRecvd = new ProtocolMessage(packet.getData());
                            System.out.println(msgRecvd); //dbgging
                            if(!msgRecvd.equals(Protocol.synMessage))
                                throw new ProtocolException("Request not recognized, possibly malformed");

                            InetAddress address = packet.getAddress();
                            int port = packet.getPort();
                            InetSocketAddress guest = new InetSocketAddress(address,port);


                            if(guestMap.containsKey(guest)){
                                guestMap.get(guest).add(socket.getLocalPort());   //refactor it later

                                if(guestMap.get(guest).equals(key)){
                                    ServerClientService serverClientService = new ServerClientService();
                                    int establishedPort = serverClientService.serverSocket.getLocalPort();
                                    System.out.println("Guest: " + address + ":" + port+ " authenticated sending tcp port: " + establishedPort);

                                    ProtocolMessage auth = Protocol.authSuccess;
                                    auth.setValue(establishedPort);
                                    sendBuffer = auth.toByte();
                                    socket.send(new DatagramPacket(sendBuffer,sendBuffer.length, address, port));

                                    serverClientService.run();
                                }

                                else if(key.size() < guestMap.get(guest).size()){
                                    guestMap.remove(guest);
                                }
                            }

                            else{
                                List<Integer> list = new ArrayList<>();
                                List<Integer> synchlist = Collections.synchronizedList(list);
                                synchlist.add(socket.getLocalPort());
                                guestMap.put(guest, synchlist);
                            }

                            sendBuffer = Protocol.ackMessage.toByte();
                            DatagramPacket confirmation = new DatagramPacket(sendBuffer, sendBuffer.length, address, port);
                            socket.send(confirmation);

                        }catch (SocketTimeoutException e){
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }

                }
            };
            t.setDaemon(true);  //inne wątki nie moga istniec bez procesu main
            t.start();

        }

        Scanner s = new Scanner(System.in);
        System.out.println("Naciśnij "Enter" aby wyjść.....");
        s.nextLine();
    }

}

Служба TCP сервер-клиент

package com.company;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerClientService implements Runnable {
    ServerSocket serverSocket;

    ServerClientService(){
        try {
            serverSocket = new ServerSocket(0);
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("Port niedostepny");
        }
    }

    @Override
    public void run() {
        try(    Socket clientSocket = serverSocket.accept();
                PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))
        )
        {
            String query = in.readLine();
            System.out.println(query);
            String response = "hello there client " + getPort();
            out.println(response);
            out.flush();


            serverSocket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public int getPort() {
        return serverSocket.getLocalPort();
    }
}

Клиент

package com.company;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

public class Client {
    byte[] sendBuffer;
    byte[] recvBuffer;
    DatagramSocket socket;
    String hostName;

    List<Integer> key;


    Client(String address, int... ports) throws SocketException {
        this.key = new ArrayList<>();
        this.sendBuffer = new byte[2048];
        this.recvBuffer = new byte[2048];
        this.socket = new DatagramSocket();
        this.hostName = address;
        for(int i : ports)
            this.key.add(i);
    }

    public void run() {
        try {
            InetAddress inetAddress = InetAddress.getByName(hostName);
            for(Integer port : key){

                sendBuffer = Protocol.synMessage.toByte();
                DatagramPacket packet = new DatagramPacket(sendBuffer, sendBuffer.length, inetAddress,port);
                socket.send(packet);
                //System.out.println("sent: " + new ProtocolMessage(sendBuffer));

                DatagramPacket returnPacket = new DatagramPacket(recvBuffer, recvBuffer.length);
                returnPacket.setLength(returnPacket.getLength());
                socket.setSoTimeout(5000);
                try {
                    socket.receive(returnPacket);
                } catch (SocketTimeoutException e){
                    System.err.println("No response, probably invalid authentication");
                }
                ProtocolMessage response = new ProtocolMessage(returnPacket.getData());
                System.out.println(response); //debugging

                if (response.equals(Protocol.ackMessage)) {
                    //proceed
                    continue;
                }
                else if(response.equals(Protocol.authSuccess)){
                    //connect to sent tcp port
                    int portNumber = response.value;
                    startTcpConnection(portNumber);
                    break;
                }

                else{
                    throw new ProtocolException("Response not recognized, possibly malformed");
                    //should like catch it and try again perhaps
                }

            }


        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        socket.close();

    }

    public void startTcpConnection(int port ){
        try(Socket tcpSocket = new Socket(hostName, port);
            PrintWriter out = new PrintWriter(tcpSocket.getOutputStream());
            BufferedReader in = new BufferedReader(new InputStreamReader(tcpSocket.getInputStream()));)
        {

            out.println("Client " + port + ": hello");
            out.flush();
            String response = in.readLine();
            System.out.println(response);


        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

Общий протокол

package com.company;

public class Protocol {
    final static ProtocolMessage synMessage = new ProtocolMessage(1);
    final static ProtocolMessage ackMessage = new ProtocolMessage(2);
    final static ProtocolMessage authSuccess = new ProtocolMessage(3);

}
package com.company;

import java.nio.ByteBuffer;

public class ProtocolMessage {
    int type;
    int value;

    ProtocolMessage(int type, int value){
        this.type = type;
        this.value = value;
    }
    ProtocolMessage(int type){
        this.type = type;
        this.value = 0;
    }
    ProtocolMessage(byte[] bytes){
        ByteBuffer wrapped = ByteBuffer.wrap(bytes);
        this.type = wrapped.getInt(0);
        this.value = wrapped.getInt(50);
    }

    public byte[] toByte(){
        ByteBuffer byteBuffer = ByteBuffer.allocate(2048);
        byteBuffer.putInt(0,this.type);
        byteBuffer.putInt(50,this.value);

        return byteBuffer.array();
    }

    @Override
    public String toString(){
        return type + ":" + value;
    }

    @Override
    public boolean equals(Object o){
        ProtocolMessage another = (ProtocolMessage) o;
        if(another.type == this.type)
            return true;
        else
            return false;
    }

    void setValue(int value){
        this.value = value;
    }
}

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *