【发布时间】:2018-06-11 10:05:31
【问题描述】:
我在这个废话上花了 50 多个小时,为什么我的 UDP 实现不起作用?问题是服务器没有收到UDP数据包。我制作了服务器应用程序以在控制台中记录事件,但我发现它没有收到任何东西。这是我遵循的 SOCKS5 文档:https://www.ietf.org/rfc/rfc1928.txt
byte[] response = new byte[256];
int responseLength;
Socket socket = new Socket(proxyHost, proxyPort);
DatagramSocket clientSocket = new DatagramSocket();
DataOutputStream writer = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
DataInputStream reader = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
// connect/authorization request
writer.writeByte(0x05); // VER
writer.writeByte(1); // NMETHODS
writer.writeByte(0); // METHODS
writer.flush();
// connect/authorization response
responseLength = reader.read(response); // RESPONSE IS: 5 0
// udp associate request
writer.writeByte(0x05); // VER
writer.writeByte(0x03); // CMD - UDP ASSOCIATE
writer.writeByte(0x00); // RSV
writer.writeByte(0x01); // ATYP
// is what I'm sending here as DST.ADDR & DST.PORT okay?
writer.write(clientSocket.getLocalAddress().getAddress()); // DST.ADDR
writer.writeShort(clientSocket.getLocalPort()); // DST.PORT
//writer.write(InetAddress.getByName(trackerHost).getAddress());
//writer.writeShort(trackerPort);
writer.flush();
// udp associate response
reader.skipBytes(4); // skip VER, REP, RSV, ATYP bytes
relayAddress = reader.readInt();
InetAddress relayInetAddress = InetAddress.getByAddress(ByteBuffer.allocate(4).putInt(relayAddress).array());
relayPort = reader.readUnsignedShort(); // server returns some random port
// connect to relay server via datagramsocket
clientSocket.connect(relayInetAddress, relayPort);
// send package to destination server
ByteBuffer byteBuffer = ByteBuffer.allocate(16 + 10);
//header - 10 bytes
byteBuffer.putShort((short) 0); // RSV
byteBuffer.put((byte) 0); // FRAG
byteBuffer.put((byte) 1); // ATYP
byteBuffer.put(trackerInetAddress.getAddress()); // DST.ADDR
byteBuffer.putShort((short) targetPort); // DST.PORT
//packet data
byteBuffer.putLong(1);
byteBuffer.putInt(0);
byteBuffer.putInt(1);
// send packet
packet = byteBuffer.array();
DatagramPacket sendPacket = new DatagramPacket(packet, packet.length);//, relayInetAddress, relayPort);
clientSocket.send(sendPacket); // SERVER DOES NOT RECEIVE THIS
验证目标主机在没有代理的情况下可以 100% 正常工作。使用来自https://blazingseollc.com/proxy/ 的支持 SOCKS5 的半专用代理
【问题讨论】:
-
你为什么用
Reader读取字节?你为什么同时滥用Reader.ready()和InputStream.available()? -
@EJP 请详细说明,这有什么问题? InputStream.available() 返回可供读取的字节数。我正在使用 ready() 以等待响应数据包到达。它适用于这部分,我收到身份验证和 udp 关联响应很好。读取(或更类似于接收)的问题仅出现在 DatagramSocket 部分。当然,在那部分之前可能已经犯了错误。任何可能的解决方案线索都是金,所以让我知道
-
1.
Reader读取char,而不是byte。 2.while (!inputStreamReader.ready());除了抽你的 CPU 之外什么也没做,因为下面的读取无论如何都会阻塞。 3.有一个具体的警告,不要像你一样使用available()。这都在 Javadoc 中。您也完全忽略了响应的内容;您还假设有响应而不是断开连接,并且响应表明成功。您需要解析它,并且这样做作为字节。你会发现DataInputStream的方法很有用。而不是所有这些废话。 -
@EJP 好的,我用 DataInputStream 和 DataOutputStream 更新了代码;但这不是问题的代码之美,所以它没有解决任何问题
-
我不是在谈论“美”,我是在谈论正确性。 编写与 Javadoc 不一致的代码是不正确的。我发表了我的评论作为评论,而不是作为答案。我现在要问你为什么不对响应进行错误检查。
标签: java sockets udp socks datagram