首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java中的简单STUN客户端

java中的简单STUN客户端
EN

Stack Overflow用户
提问于 2014-12-14 12:43:23
回答 2查看 7.7K关注 0票数 4

我已经找到了几个java STUN实现。

Java和我应该使用哪个眩晕库?

的确有

  • JSTUN:http://jstun.javawi.de/
  • 眩晕:http://java.net/projects/stun

另见:眩晕,转向,ICE Java库

但它是有很多类的罐子。我希望能找到一些简单的方法,或者至少是单个的小班。就像下面的python代码。

.py

合理地回答为什么Java中的眩晕是如此巨大也是可以接受的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-20 20:48:26

合理地回答为什么Java中的眩晕是如此巨大也是可以接受的。

这是个合理的问题。99%的STUN只是一个简单的回波/响应协议,客户端通过NAT在它和公共internet之间自我发现IP和端口映射。在构建了C++中的眩晕库之后,我有了一些见解。

让我们考虑一下眩晕库所需的内容:

  • 使用属性字段架构生成STUN消息的消息编写器,该架构不仅允许字段以任何顺序出现,而且还允许添加自定义属性。
  • 一种消息解析器,它可以读取这些消息并转换代码使用的合理的数据结构。它需要安全地这样做,并避免未处理的异常。
  • 用于发送/接收此类消息的套接字网络代码。技术上,STUN服务器需要侦听2个IP和2个端口,这使得服务器的网络代码更加复杂。
  • 如果我们只关心绑定请求和绑定响应,我们就完成了。但是STUN RFCs也定义了一组NAT分类测试。因此,需要额外的状态机逻辑来完成任何这样的库。
  • 如果STUN库要使用协议提供的安全选项,那么它需要一定数量的加密代码来对消息进行散列和签名。

因此,将所有这些合并到一个库中,任何人都可以用于眩晕的所有不同用途--包括映射地址发现、NAT分类和ICE协商--它开始变得非常迅速。

您可以轻松地滚出一些套接字代码,这些套接字代码硬编码绑定请求的字节,然后一些套接字解析解析以解析响应。这可能会满足您自己的需求,但是一个成熟的开源库永远不会这样编写。

JSTUN是一个很好的开始。我与原始作者共享了一些互操作和错误修复代码。他没有积极维护它,但是它是RFC 3489的一个很好的实现。我甚至黑了一次,让它在Android上运行。

若要在JSTUN中生成STUN绑定请求,请执行以下操作。

代码语言:javascript
复制
MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
sendMH.generateTransactionID();

// add an empty ChangeRequest attribute. Not required by the standard, but JSTUN server requires it
ChangeRequest changeRequest = new ChangeRequest();
sendMH.addMessageAttribute(changeRequest);

byte[] data = sendMH.getBytes();

// not shown - sending the message

然后解析响应:

代码语言:javascript
复制
byte [] receivedData = new byte[500];

// not shown - socket code that receives the messages into receivedData
receiveMH.parseAttributes(receivedData);
MappedAddress ma = (MappedAddress) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.MappedAddress);    

然后将上面的内容与一些套接字代码结合起来。以上与套接字代码组合的最佳示例可以在DiscoveryTest.java源文件中找到。您确实需要这个类的test1()方法中的代码。

票数 7
EN

Stack Overflow用户

发布于 2019-08-05 00:17:25

代码语言:javascript
复制
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import de.javawi.jstun.attribute.ChangeRequest;
import de.javawi.jstun.attribute.ChangedAddress;
import de.javawi.jstun.attribute.ErrorCode;
import de.javawi.jstun.attribute.MappedAddress;
import de.javawi.jstun.attribute.MessageAttribute;
import de.javawi.jstun.attribute.MessageAttributeException;
import de.javawi.jstun.attribute.MessageAttributeParsingException;
import de.javawi.jstun.header.MessageHeader;
import de.javawi.jstun.header.MessageHeaderParsingException;
import de.javawi.jstun.util.UtilityException;


public class StunTest { public static void main(String[] args) throws UtilityException, IOException {


        MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
        // sendMH.generateTransactionID();

        // add an empty ChangeRequest attribute. Not required by the
        // standard,
        // but JSTUN server requires it

        ChangeRequest changeRequest = new ChangeRequest();
        sendMH.addMessageAttribute(changeRequest);

        byte[] data = sendMH.getBytes();


        DatagramSocket s = new DatagramSocket();
        s.setReuseAddress(true);

        DatagramPacket p = new DatagramPacket(data, data.length, InetAddress.getByName("stun.l.google.com"), 19302);
        s.send(p);

        DatagramPacket rp;

        rp = new DatagramPacket(new byte[32], 32);

        s.receive(rp);
        MessageHeader receiveMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingResponse);
        // System.out.println(receiveMH.getTransactionID().toString() + "Size:"
        // + receiveMH.getTransactionID().length);
        try {
                receiveMH.parseAttributes(rp.getData());
        } catch (MessageAttributeParsingException e) {
                e.printStackTrace();
        }
        MappedAddress ma = (MappedAddress) receiveMH
                .getMessageAttribute(MessageAttribute.MessageAttributeType.MappedAddress);
        System.out.println(ma.getAddress()+" "+ma.getPort());
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27469398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档