【问题标题】:Sending TCP urgend data through the socket in Java通过 Java 中的套接字发送 TCP 紧急数据
【发布时间】:2020-06-23 06:00:09
【问题描述】:

如何在Java中使用“TCP紧急数据”实现传输控制。

我实现了一个客户端-服务器应用程序,用于使用 TCP 协议传输文件。服务器是并行的。还需要使用紧急数据来实现传输控制。我在网上没有找到关于Java的解决方案。

服务器类:

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

【问题讨论】:

  • 也许您正在寻找错误的术语。您如何定义“紧急数据”以及您预计会发生什么?
  • 能否请您通过服务器和客户端的控制台输出并进行测试?还有原始和生成的文件内容。
  • 我的回答对您有帮助还是有歧义?

标签: java sockets networking tcp network-programming


【解决方案1】:

来自哈罗德的“Java Network Programming”:

TCP 包含一项功能,可将单个字节的“紧急”数据发送出去 的乐队。该数据会立即发送。此外,接收机是 收到紧急数据时通知并可以选择处理 在处理任何其他数据之前的紧急数据 已收到。 Java支持发送和接收这样的紧急 数据。发送方法被命名为,很明显,sendUrgentData():

public void sendUrgentData(int data) throws IOException

此方法几乎立即发送其参数的最低位字节*。如果 必要时,首先刷新所有当前缓存的数据。

接收端如何响应紧急数据有点迷茫, 并且从一个平台和 API 到下一个平台和 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 无法将其与非紧急数据区分开来。这使得它小于 非常有用,但如果你有一个特定的字节(例如,一个 Ctrl-C) 对你的程序有特殊意义并且永远不会出现在 常规数据流,那么这将使您能够发送更多 很快。

GitHub上有很多使用sendUrgentData()setOOBInline()的例子。例如。 this.

* - 请记住,几乎所有实现实际上只能提供 一个字节的“带外数据”

阅读更多:

【讨论】:

    猜你喜欢
    • 2011-12-11
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2012-10-13
    • 2020-12-03
    • 2016-02-17
    • 2019-04-26
    • 2011-05-03
    相关资源
    最近更新 更多