У меня возникла следующая проблема с DatagramSockets:
java.io.IOException: Operation is not permitted.
at java.net.PlainDatagramSocketImpl.send(Native Method)
at java.net.DatagramSocket.send(DatagramSocket.java:693)
Исключение возникает случайным образом, и я не вижу закономерности. Это усложняет мне отладку этого.
Тем не менее, я подозреваю, что это происходит чаще, когда я отправляю много данных.
У меня есть несколько потоков, отправляющих через этот сокет, но это не должно быть проблемой, так как я читал, что сокеты Java будут потокобезопасными.
Может ли кто-нибудь сказать мне, когда и при каких условиях может быть выбрано такое исключение?
Вот мой основной сетевой код:
package de.oompf.netwrk;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
class Server implements Runnable {
private final EventBus bus;
private final Thread serverThread;
private final DatagramSocket socket;
Server(EventBus bus) throws SocketException {
this.bus = bus;
serverThread = new Thread(this, "Server Thread");
socket = getBoundSocket();
socket.setSoTimeout(2400);
}
private static DatagramSocket getBoundSocket() throws SocketException {
for (int port : Configuration.getPortList()) {
try {
return new DatagramSocket(port);
} catch (SocketException e) {
}
}
return new DatagramSocket(0);
}
int getPort() {
return socket.getLocalPort();
}
void start() {
bus.subscribe(this);
serverThread.start();
}
void stop() {
serverThread.interrupt();
socket.close();
}
@Override
public void run() {
DatagramPacket p = new DatagramPacket(new byte[4096], 4096);
while (!serverThread.isInterrupted()) {
try {
socket.receive(p);
bus.publish(new IncomingPacket(p.getData(), p.getLength(), p.getAddress(), p.getPort()));
} catch (IOException e) {
if (socket.isClosed()) {
break;
}
}
}
}
void send(OutgoingPacket p) {
try {
if (p.getData()[0] == 0x03) {
}
socket.send(new DatagramPacket(p.getData(), p.getData().length, p.getSocketAddress()));
} catch (IOException e) {
if (socket.isClosed()) {
serverThread.interrupt();
} else {
e.printStackTrace();
}
}
}
}
За этим стоит множество классов. Я просто опубликую несколько строк, где заканчивается моя трассировка стека.
private void handleBootstrapRequest(IncomingPacket p) {
if (p.getLength() == 21) {
byte[] requestNodeBytes = new byte[20];
System.arraycopy(p.getData(), 1, requestNodeBytes, 0, 20);
try {
Node requestNode = new Node(requestNodeBytes);
if (needsRelay(requestNode)) {
byte[] forwardPacket = new byte[47];
forwardPacket[0] = 0x07;
System.arraycopy(requestNode.getBytes(), 0, forwardPacket, 1, 20);
System.arraycopy(me.getBytes(), 0, forwardPacket, 21, 20);
System.arraycopy(p.getAddress().getAddress(), 0, forwardPacket, 41, 4);
System.arraycopy(ByteBuffer.allocate(2).putShort((short) (p.getPort() - Short.MAX_VALUE)).array(), 0, forwardPacket, 45, 2);
/* Will send a packet (doing some routing first) */
relay(forwardPacket, requestNode);
} else {
List<Neighbour> references = routing.getClosest(requestNode, 7);
byte[] answerPacket = new byte[2 + references.size() * 26];
answerPacket[0] = 0x06;
answerPacket[1] = (byte) references.size();
for (int i = 0; i < references.size(); i++) {
Neighbour n = references.get(i);
System.arraycopy(n.getBytes(), 0, answerPacket, 2 + i * 26, 20);
System.arraycopy(n.getAddress().getAddress().getAddress(), 0, answerPacket, 22 + i * 26, 4);
System.arraycopy(ByteBuffer.allocate(2).putShort((short) (n.getAddress().getPort() - Short.MAX_VALUE)).array(), 0, answerPacket, 26 + i * 26, 2);
}
/* That's where my stack trace ends and where the packet gets onto an event bus (100% working properly) */
bus.publish(new OutgoingPacket(answerPacket, p.getSocketAddress()));
}
byte[] quickResponse = new byte[21];
quickResponse[0] = 0x02;
System.arraycopy(me.getBytes(), 0, quickResponse, 1, 20);
/* see last comment */
bus.publish(new OutgoingPacket(quickResponse, p.getSocketAddress()));
} catch (InvalidNodeException e) {
}
}
}
Как я уже сказал, возможно, что несколько исходящих пакетов находятся на шине событий, когда несколько обработчиков пакетов вызываются моими пулами обработчиков пакетов.
DatagramPacket,
или, по крайней мере, сбрасывать его длину каждый раз в цикле приема. В противном случае он может продолжать уменьшаться до размера наименьшей полученной до сих пор дейтаграммы. @ Крис Спасибо за бесполезное разъяснение. - person user207421   schedule 23.01.2015