繁体   English   中英

如何在UDP封装一个SCTP包,在java通过UDP通道发送

[英]How to encapsulate a SCTP packet in UDP and send it over UDP channel in java

我必须使用 SCTP 协议传输文件。 我已经在 java 中编写了代码,但是当我使用 4G hotspot.network 时代码不起作用。 所以我遇到了这个 RFC,它讨论了 SCTP 的 UDP 封装。 我想知道是否有一个实现可以用来将 SCTP 数据包封装在 UDP 中并通过 UDP 通道发送它,以便它可以大量遍历 NATted.network。 我目前发送数据包的代码如下:

import java.io.*;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.*;

import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;

public class Main {
    SctpChannel connectionChannelPrimary;
    SctpChannel connectionChannelSecondary;
    InetSocketAddress serverSocketAddressPrimary;
    InetSocketAddress serverSocketAddressSecondary;

    String directoryPath;

    public Main() {
        serverSocketAddressPrimary = new InetSocketAddress(6002);
        serverSocketAddressSecondary = new InetSocketAddress(6003);
    }

    public void setDirectoryPath(String directoryPath) {
        this.directoryPath = directoryPath;
    }

    public String getDirectoryPath() {
        return directoryPath;
    }

    public void establishConnection(int connId) throws IOException {
        SctpServerChannel sctpServerChannel = SctpServerChannel.open();
        if (connId == 0) {
            sctpServerChannel.bind(serverSocketAddressPrimary);
            connectionChannelPrimary = sctpServerChannel.accept();
            System.out.println("connection established for primary");
        } else {
            sctpServerChannel.bind(serverSocketAddressSecondary);
            connectionChannelSecondary = sctpServerChannel.accept();
            System.out.println("connection established for helper");
        }

    }

    ArrayList<String> getAllFiles() {
        File directory = new File(this.directoryPath);
        ArrayList<String> fileNames = new ArrayList<>();
        for (File fileEntry : Objects.requireNonNull(directory.listFiles())) {
            if (fileEntry.isFile()) {
                fileNames.add(fileEntry.getName());
            }
        }
        Collections.sort(fileNames);
        return fileNames;
    }

    public byte[] readFile(String filename) throws IOException {
        String extraString = "\n\n\n\nNRL\n\n\n";
        File file = new File(filename);
        FileInputStream fl = new FileInputStream(file);
        ByteBuffer finalBuffer = ByteBuffer.allocate((int) (file.length() + extraString.length()));
        byte[] arr = new byte[(int) file.length()];
        int res = fl.read(arr);
        if (res < 0) {
            System.out.println("Error in reading file");
            fl.close();
            return null;
        }
        fl.close();
        finalBuffer.put(arr);
        finalBuffer.put(extraString.getBytes());
        byte[] tmp = new byte[extraString.length()];
        finalBuffer.position((int) (file.length() - 1));
        finalBuffer.get(tmp, 0, tmp.length);
        return finalBuffer.array();
    }

    public void sendBytes(String filename, int connId) throws IOException {
        byte[] message = readFile(filename);
        assert message != null;
        System.out.println(message.length);
        int tmp = 0;
        int cntIndex = 60000;
        int prevIndex = 0;
        boolean isBreak = false;
        while (!isBreak) {
            byte[] slice;
            if (prevIndex + 60000 >= message.length) {
                slice = Arrays.copyOfRange(message, prevIndex, message.length);
                isBreak = true;
            } else {
                slice = Arrays.copyOfRange(message, prevIndex, cntIndex);
                prevIndex = cntIndex;
                cntIndex = cntIndex + 60000;
            }
            final ByteBuffer byteBuffer = ByteBuffer.allocate(64000);
            final MessageInfo messageInfo = MessageInfo.createOutgoing(null, 0);
            byteBuffer.put(slice);
            byteBuffer.flip();
            tmp += slice.length;
            try {
                if (connId == 0) connectionChannelPrimary.send(byteBuffer, messageInfo);
                else connectionChannelSecondary.send(byteBuffer, messageInfo);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(tmp);
    }

    public static void main(String[] args) throws IOException {
        String bgFilePath = "/home/iiitd/Desktop/background/";
        String fgFilePath = "/home/iiitd/Desktop/foreground/";
        Main myObj = new Main();
        myObj.setDirectoryPath("/home/iiitd/Desktop/tmp/");
        myObj.establishConnection(1);
        myObj.establishConnection(0);
        ArrayList<String> files = myObj.getAllFiles();

        for (String tmpFile : files) {
            String cntFilePath = myObj.getDirectoryPath() + tmpFile;
            
            myObj.sendBytes(cntFilePath,0);
        }
    }
}

RFC 链接: https://datatracker.ietf.org/doc/html/draft-ietf-tsvwg-sctp-udp-encaps-09

在 C 中,我认为usrsctp是 UDP 上 SCTP 的一个流行实现。如果我理解正确的话,它曾被谷歌浏览器使用过(尽管我看到他们提到在某些时候转向“dcsctp”)。 也在 2016 年的 Firefox 来源的镜像中看到了它,不知道今天的 state 是什么。

因此,一种解决方案是使用 JNI 包装usrsctp 看起来这正是jitsi-sctp正在做的事情。 我没用过,但我想看看。

暂无
暂无

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

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