TCP-und UDP-Anfragen auf den selben port
Ich Schreibe eine Client - /Server-Programme
Je nach operation, die vom client angefordert, die ich verwenden, stellen Sie die TCP-oder UDP-Anfrage.
Implementierung der client-Seite ist straight-forward, da kann ich leicht öffnen Sie Verbindung mit einem beliebigen Protokoll und senden Sie die Anfrage an der server-Seite.
Auf der Server-Seite, auf der anderen Seite, würde ich gerne hören, sowohl für die UDP-und TCP-verbindungen auf dem gleichen port. Außerdem mag ich die der server zum öffnen von neuen Threads für jede Verbindung Anfrage.
Habe ich angenommen, das Konzept erläutert: link-text
Habe ich erweitert dieses code-Beispiel durch das erstellen von neuen threads für die einzelnen TCP/UDP-Anfrage.
Dies funktioniert einwandfrei, wenn ich nur TCP, aber es schlägt fehl, wenn ich Versuch zu machen, UDP-Bindungen.
Bitte geben Sie mir irgendeinen Vorschlag, wie kann ich das korrigieren.
tnx
Hier ist der Server-Code:
public class Server {
public static void main(String args[]) {
try {
int port = 4444;
if (args.length > 0)
port = Integer.parseInt(args[0]);
SocketAddress localport = new InetSocketAddress(port);
//Create and bind a tcp channel to listen for connections on.
ServerSocketChannel tcpserver = ServerSocketChannel.open();
tcpserver.socket().bind(localport);
//Also create and bind a DatagramChannel to listen on.
DatagramChannel udpserver = DatagramChannel.open();
udpserver.socket().bind(localport);
//Specify non-blocking mode for both channels, since our
//Selector object will be doing the blocking for us.
tcpserver.configureBlocking(false);
udpserver.configureBlocking(false);
//The Selector object is what allows us to block while waiting
//for activity on either of the two channels.
Selector selector = Selector.open();
tcpserver.register(selector, SelectionKey.OP_ACCEPT);
udpserver.register(selector, SelectionKey.OP_READ);
System.out.println("Server Sterted on port: " + port + "!");
//Load Map
Utils.LoadMap("mapa");
System.out.println("Server map ... LOADED!");
//Now loop forever, processing client connections
while(true) {
try {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
//Iterate through the Set of keys.
for (Iterator<SelectionKey> i = keys.iterator(); i.hasNext();) {
SelectionKey key = i.next();
i.remove();
Channel c = key.channel();
if (key.isAcceptable() && c == tcpserver) {
new TCPThread(tcpserver.accept().socket()).start();
} else if (key.isReadable() && c == udpserver) {
new UDPThread(udpserver.socket()).start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
System.err.println(e);
System.exit(1);
}
}
}
Den UDPThread code:
public class UDPThread extends Thread {
private DatagramSocket socket = null;
public UDPThread(DatagramSocket socket) {
super("UDPThread");
this.socket = socket;
}
@Override
public void run() {
byte[] buffer = new byte[2048];
try {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String inputLine = new String(buffer);
String outputLine = Utils.processCommand(inputLine.trim());
DatagramPacket reply = new DatagramPacket(outputLine.getBytes(), outputLine.getBytes().length,
packet.getAddress(), packet.getPort());
socket.send(reply);
} catch (IOException e) {
e.printStackTrace();
}
socket.close();
}
}
Ich erhalten:
Exception in thread "UDPThread" java.nio.channels.IllegalBlockingModeException
at sun.nio.ch.DatagramSocketAdaptor.receive(Unknown Source)
at server.UDPThread.run(UDPThread.java:25)
10x
- Schlägt fehl, wie? Haben Sie mehr Informationen, wie Fehlermeldungen oder Beispielcode?
- Bitte erläutern Sie "schlägt es" im detail.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sollte es funktionieren. Eines der Probleme mit diesem code, es scheint, ist, dass der ByteBuffer Größe auf 0 gesetzt ist, was bedeutet, dass das Datagramm wird verworfen (wie erwähnt in den Kommentaren). Wenn Sie brauchen, um erhalten alle Informationen über UDP und Sie sind auf ein zuverlässiges Netzwerk, können Sie die Größe ziemlich groß und empfangen großer Datenpakete aus mehreren Paketen. Ansonsten, auf ein unzuverlässiges Netzwerk, stellen Sie hier die MTU-Größe. Stellen Sie sicher, dass Sie die flip() die ByteBuffer nach Erhalt alles drin.
Auch ist das erstellen von neuen threads für jede Anforderung eine schlechte Idee ist, erstellen Sie eine "session" thread für jede andere IP erhalten Sie in eine HashMap oder so, und dann machen Sie eine bewacht block auf das session-Objekt. Aufwachen, der thread schlafen auf das Objekt, wenn Sie eine Nachricht erhalten, nach der übergabe von neuen Informationen. Die Selektor-code, den Sie haben, ist entworfen, um vermeiden die Erstellung von threads in dieser Art und Weise.
Edit: basierend auf dem obigen code bist du erstellen Sie eine Datagramm-Kanal und dann über den socket empfangen-Datagramme direkt? Das ist nicht sinnvoll. Verwenden Sie die channel-Methoden, die erst nach Bindung des Kanals. Auch nicht, dies in einem separaten thread. Dein code ist nicht thread-sicher und verliert sich nach oben. Hand der erhaltenen Informationen aus der separaten 'session' - thread, wie bereits erwähnt. Der Selektor ist ausgelegt, Ihnen zu sagen, welche Kanäle können gelesen werden ohne zu blockieren (obwohl die Blockierung ist deaktiviert, wie auch immer, so wird es Ihnen sagen, welche Kanäle Daten zum Lesen aus).
DatagramSocket
von einer non-blockingDatagramChannel
und dann mit seinerreceive()
- Methode wird nicht unterstützt, und wirft die exception, die der OP bekam.AFAIK, sollten Sie in der Lage zu hören, die sowohl für TCP-verbindungen und UDP-Nachrichten auf dem gleichen port. Würde es helfen, wenn Sie veröffentlicht Ihre UDP-code, und die exception + stacktrace, die Sie sehen.
Können Sie nicht verwenden
DatagramSocket.receive()
im nicht-blockierenden Modus. Verwenden Sie dieread()
oderreceive()
Methoden IhrerDatagramChannel
direkt.In der Tat, wie Sie mit non-blocking-Modus und eine
Selector
ist es ganz unmöglich zu sehen, warum bist du auch mit einemUDPThread
überhaupt. Rufen Sie einfachudpserver.receive()
anstelle des starten des thread.