Отправка данных TCP urgend через сокет в Java - PullRequest
0 голосов
/ 11 марта 2020

Как реализовать управление передачей с использованием «Срочные данные TCP» в Java.

Я реализовал клиент-серверное приложение для передачи файла по протоколу TCP. Сервер параллельный. Также необходимо реализовать контроль передачи с использованием срочных данных. Я не нашел решения на Java на Inte rnet.

Класс сервера:

import javafx.beans.binding.Bindings;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    private static final String FILE_PATH_SERVER = "C:\\Users\\anduser\\IdeaProjects\\Shafarenko_LR1\\src\\main\\resources\\fileServer.txt";

    public static final File FILE_SERVER = new File(FILE_PATH_SERVER);

    private ServerSocket serverSocket;

    public void start(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        while (true)
            new ClientHandler(serverSocket.accept()).start();
    }

    public void stop() throws IOException {
        serverSocket.close();
    }

    private static class ClientHandler extends Thread {
        private Socket clientSocket;
        private DataOutputStream out;
        private FileInputStream in;

        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }

        public void run() {
            try {
                out = new DataOutputStream(clientSocket.getOutputStream());
                out.writeInt((int) FILE_PATH_SERVER.length());
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                in = new FileInputStream(FILE_PATH_SERVER);
            } catch (IOException e) {
                e.printStackTrace();
            }

            while (true) {
                byte buf[] = new byte[8];
                int len = 0;
                try {
                    len = in.read(buf);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (len == -1) {
                    break;
                }
                try {
                    out.write(buf, 0, len);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    out.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

Класс клиента:

import org.apache.commons.lang3.RandomStringUtils;

import java.io.*;
import java.net.Socket;

public class Client {
    private String generatedFileClient = RandomStringUtils.randomAlphanumeric(10) + ".txt";
    private String FILE_PATH_CLIENT = "C:\\Users\\anduser\\IdeaProjects\\Shafarenko_LR1\\src\\test\\resources\\" + generatedFileClient;

    private Socket clientSocket;
    private FileOutputStream out;
    private DataInputStream in;
    private File fileCilent;

    public File getFileClient() {
        return new File(FILE_PATH_CLIENT);
    }

    public void getFile() throws IOException {
        int i = 0;
        int len;
        byte buf[] = new byte[8];
        int fileSize;
        fileSize = in.readInt();
        while (i < fileSize) {
            len = in.read(buf);
            if (len == -1) {
                break;
            }
            i += len;
            out.write(buf, 0, len);
            out.flush();
        }
        out.close();
    }

    public void startConnection(String ip, int port) throws IOException {
        clientSocket = new Socket(ip, port);
        out = new FileOutputStream(FILE_PATH_CLIENT);
        in = new DataInputStream(clientSocket.getInputStream());
    }

    public void stopConnection() throws IOException {
        in.close();
        out.close();
        clientSocket.close();
    }
}

Тест:

public class TestClient {
    @Test(threadPoolSize = 10, invocationCount = 1000, timeOut = 0)
    public void givenClient() throws IOException, InterruptedException {
        SoftAssert softAssert = new SoftAssert();
        Client client = new Client();
        client.startConnection("127.0.0.1", 555);
        client.getFile();
        softAssert.assertTrue(FileUtils.contentEquals(Server.FILE_SERVER, client.getFileClient()), "The files differ!");
        client.stopConnection();
        softAssert.assertAll();
    }
}

1 Ответ

0 голосов
/ 12 марта 2020

Из Гарольда "Java Сетевое программирование ":

TCP включает функцию, которая отправляет один байт "срочных" данных вне диапазона. Эти данные отправляются немедленно. Кроме того, получатель уведомляется о получении срочных данных и может выбрать обработку срочных данных до обработки любых других данных, которые уже были получены. Java поддерживает отправку и получение таких срочных данных. Метод отправки назван, очевидно, sendUrgentData ():

public void sendUrgentData(int data) throws IOException

Этот метод отправляет байт самого младшего порядка * из его аргумент почти сразу. При необходимости все текущие кэшированные данные сначала сбрасываются.

То, как принимающая сторона реагирует на срочные данные, немного запутано и варьируется от одной платформы и API к другой. Некоторые системы получают срочные данные отдельно от обычных данных. Однако более распространенный и более современный подход заключается в том, чтобы поместить срочные данные в обычную очередь принятых данных в правильном порядке, сообщить приложению, что срочные данные доступны, и разрешить ему искать в очереди для их поиска. По умолчанию Java игнорирует срочные данные, полученные из сокета. Однако, если вы хотите получать срочные данные, встроенные в обычные данные, вам нужно установить для параметра OOBINLINE значение true, используя следующие методы: По умолчанию Java игнорирует срочные данные, полученные из сокета. Однако, если вы хотите получать срочные данные, встроенные в обычные данные, вам необходимо установить для параметра OOBINLINE значение true, используя следующие методы:

public void setOOBInline(boolean on) throws SocketException
public boolean getOOBInline() throws SocketException

Значение по умолчанию для OOBINLINE - false. Этот фрагмент кода включает OOBINLINE, если он выключен:

if (!s.getOOBInline()) s.setOOBInline(true);

После включения OOBINLINE любые срочные данные , которые поступают будет помещен во входной поток сокета и будет считываться обычным образом . Java не отличает guish это от неургентных данных . Это делает его менее чем полезным в идеале, но если у вас есть определенный байт (например, Ctrl- C), который имеет особое значение для вашей программы и никогда не отображается в обычном потоке данных, то это позволит вам отправить его быстрее.

На GitHub есть множество примеров использования sendUrgentData() и setOOBInline(). Например, это .

* - помните, что почти все реализации действительно могут обеспечить только один байт "out" данных диапазона ".

Подробнее:

...