简体   繁体   English

Java中通过套接字发送TCP紧急数据

[英]Sending TCP urgend data through the socket in Java

How to implement transfer control using "TCP urgent data" in Java. Java中如何使用“TCP紧急数据”实现传输控制。

I implemented a client-server application for transferring a file using the TCP protocol.我实现了一个客户端-服务器应用程序,用于使用 TCP 协议传输文件。 Server is parallel.服务器是并行的。 It is also necessary to implement transmission control using urgent data.还需要使用紧急数据来实现传输控制。 I did not find a solution on Java on the Internet.我没有在互联网上找到有关 Java 的解决方案。

Server class:服务器类:

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();
            }

        }
    }
}

Client class:客户端类:

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();
    }
}

Test:测试:

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();
    }
}

From Harold's " Java Network Programming ":来自 Harold 的“ Java 网络编程”:

TCP includes a feature that sends a single byte of “urgent” data out of band. TCP 包含一个功能,可以在带外发送单个字节的“紧急”数据。 This data is sent immediately.该数据将立即发送。 Furthermore, the receiver is notified when the urgent data is received and may elect to process the urgent data before it processes any other data that has already been received.此外,接收器在接收到紧急数据时得到通知,并且可以选择在处理已经接收到的任何其他数据之前处理紧急数据。 Java supports both sending and receiving such urgent data. Java 支持发送和接收此类紧急数据。 The sending method is named, obviously enough, sendUrgentData():发送方法被命名为,很明显,sendUrgentData():

public void sendUrgentData(int data) throws IOException

This method sends the lowest-order byte* of its argument almost immediately.此方法几乎立即发送其参数的最低字节* If necessary, any currently cached data is flushed first.如有必要,首先刷新任何当前缓存的数据。

How the receiving end responds to urgent data is a little confused, and varies from one platform and API to the next.接收端如何响应紧急数据有点混乱,并且从一个平台和 API 到另一个不同。 Some systems receive the urgent data separately from the regular data.一些系统将紧急数据与常规数据分开接收。 However, the more common, more modern approach is to place the urgent data in the regular received data queue in its proper order, tell the application that urgent data is available, and let it hunt through the queue to find it.然而,更常见、更现代的方法是将紧急数据按照正确的顺序放置在常规接收数据队列中,告诉应用程序紧急数据可用,并让它在队列中寻找它。 By default, Java ignores urgent data received from a socket.默认情况下,Java 会忽略从套接字接收到的紧急数据。 However, if you want to receive urgent data inline with regular data, you need to set the OOBINLINE option to true using these methods: By default, Java ignores urgent data received from a socket.但是,如果要接收与常规数据内联的紧急数据,则需要使用以下方法将 OOBINLINE 选项设置为 true: 默认情况下,Java 会忽略从套接字接收的紧急数据。 However, if you want to receive urgent data inline with regular data, you need to set the OOBINLINE option to true using these methods:但是,如果要接收与常规数据内联的紧急数据,则需要使用以下方法将 OOBINLINE 选项设置为 true:

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

The default for OOBINLINE is false. OOBINLINE 的默认值为 false。 This code fragment turns OOBINLINE on, if it's turned off:如果 OOBINLINE 已关闭,此代码片段将打开 OOBINLINE:

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

Once OOBINLINE is turned on, any urgent data that arrives will be placed on the socket's input stream to be read in the usual way .一旦 OOBINLINE 被打开,任何到达的紧急数据都将被放置在套接字的输入流上,以便以通常的方式读取 Java does not distinguish it from nonurgent data . Java 不会将其与非紧急数据区分开来 That makes it less than ideally useful, but if you have a particular byte (eg, a Ctrl-C) that has special meaning to your program and never shows up in the regular data stream, then this would enable you to send it more quickly.这使得它不太理想,但是如果您有一个对您的程序具有特殊意义的特定字节(例如,Ctrl-C)并且从未出现在常规数据流中,那么这将使您能够更快地发送它.

There are a lot of examples on GitHub of using sendUrgentData() and setOOBInline() . GitHub 上有很多使用sendUrgentData()setOOBInline()的例子。 Eg this .例如这个

* - remember that almost all implementations really can provide only one byte of "out-of-band data" . * - 请记住,几乎所有的实现实际上只能提供一个字节的“带外数据”

Read more:阅读更多:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM