Hi,
jemanden ein bug, häufig gemachter Fehler etc. bekannt welcher verursacht dass man auf einen nio ServerSocketChannel via
öffentlich routbarer ip nicht connecten kann?
Ich sitze hier nun 2 Stunden und versteh die Welt nicht mehr.
Es liegt NICHT an der Firewall und nicht am forewarding! Zum connect habe ich testweise einige Programme benutzt (TCP Tester, eigene Clients) und das Ergebnis ist immer das gleiche:
Serverconnect mit hostadresse "localhost" oder "127.0.0.1" haben 1a funktioniert. Wenn ich den Umweg über eine
öffentliche ip gehe oder eine dyn dns Adresse benutze schlägt die Verbindung fehl.
Java bedankt sich mit ner "java.net.ConnectException". TCP Test Tool 2.3 mit
"TCP connection failed verify remote address/port".
Bin mit meinem Latein am Ende.
Hier der Code (Einfachheitshalber auf eine Klasse zusammengefasst! - Entschuldigt die unschöne Form):
Bin für Anregungen dankbar.
Mfg Alex
jemanden ein bug, häufig gemachter Fehler etc. bekannt welcher verursacht dass man auf einen nio ServerSocketChannel via
öffentlich routbarer ip nicht connecten kann?
Ich sitze hier nun 2 Stunden und versteh die Welt nicht mehr.
Es liegt NICHT an der Firewall und nicht am forewarding! Zum connect habe ich testweise einige Programme benutzt (TCP Tester, eigene Clients) und das Ergebnis ist immer das gleiche:
Serverconnect mit hostadresse "localhost" oder "127.0.0.1" haben 1a funktioniert. Wenn ich den Umweg über eine
öffentliche ip gehe oder eine dyn dns Adresse benutze schlägt die Verbindung fehl.
Java bedankt sich mit ner "java.net.ConnectException". TCP Test Tool 2.3 mit
"TCP connection failed verify remote address/port".
Bin mit meinem Latein am Ende.
Hier der Code (Einfachheitshalber auf eine Klasse zusammengefasst! - Entschuldigt die unschöne Form):
Code:
package com.mni.utils.test.experimental;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Experimental nio tcp server
*
* @author DamienX
*
*/
public class NioServer implements Runnable{
ServerSocketChannel serverChannel;
InetSocketAddress isa;
int port;
String hostname;
Selector selector;
boolean shutdown = false;
Set<SelectionKey> blackList = new HashSet<SelectionKey>();
// allocate 10KB
ByteBuffer buffer = ByteBuffer.allocate(1024 * 10);
//encoder / decoder
// Charset charset = Charset.forName("ISO-8859-1");
Charset charset = Charset.forName("UTF-8");
CharsetEncoder encoder = charset.newEncoder();
CharsetDecoder decoder = charset.newDecoder();
public NioServer(int port, String hostname) {
this.hostname = hostname;
this.port = port;
System.out.println("Building Sockeraddress...");
isa = new InetSocketAddress(hostname, port);
System.out.println("res: " + isa.isUnresolved());
System.out.println("Done!");
init();
}
/**
* Inits selector and sChannel
*/
private void init() {
try {
System.out.println("InitSelector...");
selector = SelectorProvider.provider().openSelector();
serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(isa);
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Done!");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while(!shutdown){
try {
int selected = this.selector.select(5000);
System.out.println("Selected: " + selected);
int registered = this.selector.keys().size();
if(selected == 0 && registered != 0){
Iterator<SelectionKey> it = this.selector.keys().iterator();
while(it.hasNext()){
SelectionKey selKey = it.next();
if(selKey == serverChannel.keyFor(selector)) continue;
SocketChannel chan = (SocketChannel) selKey.channel();
long idle = ((ConnectionInfo) selKey.attachment()).getIdleTime()/1000;
System.out.println("Found pending socket: " +
chan.socket().getInetAddress().toString() + " Idle time: " + ((ConnectionInfo) selKey.attachment()).getIdleTime()/1000);
if(idle > 60){
selKey.cancel();
chan.close();
System.out.println("Client canceled -> Idle timeout!");
}
}
}
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
if(!keys.hasNext()) System.err.println("Server is pending!");
while(keys.hasNext()){
SelectionKey key = (SelectionKey) keys.next();
keys.remove();
if(!key.isValid()){
System.out.println("Found invalid key... ignore!");
continue;
}
System.out.println(key.isConnectable() +"!!!");
if(key.isAcceptable()){
System.out.println("Found acceptable key... try to accept!");
accept(key);
}
if(key.isReadable() || key.isWritable()){
ConnectionInfo info = (ConnectionInfo) key.attachment();
info.reset();
}
if(key.isReadable()){
System.out.println("Found readable key... try to read!");
SocketChannel client = (SocketChannel) key.channel();
int bytes = Integer.MIN_VALUE;
while(bytes != 0 && bytes != -1){
bytes = client.read(buffer);
System.out.println(bytes + " bytes received!");
}
if(bytes == -1){
key.cancel();
client.close();
System.out.println("Client canceled!");
continue;
}
buffer.flip();
CharBuffer requestBuffer = decoder.decode(buffer);
String request = requestBuffer.toString();
System.out.println("Client " + client.socket().getInetAddress().toString() +
": " + request);
buffer.clear();
key.interestOps(SelectionKey.OP_WRITE);
}
if(key.isWritable()){
if(blackList.contains(key)) continue;
System.out.println("Found writable key... try to write!");
buffer.clear();
SocketChannel client = (SocketChannel) key.channel();
buffer.put(encoder.encode(CharBuffer.wrap("Testrepeat!\n")));
buffer.flip();
int bytes = 0;
int bytesToWrite = buffer.remaining();
int zeroByteWrites = 0;
System.out.println("We have " + bytesToWrite + " bytes to write!");
while(buffer.hasRemaining()){
bytes = client.write(buffer);
System.out.println(bytes + " bytes written!");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//ok we had a zero write turn... could happen
if(bytes == 0){
zeroByteWrites++;
System.out.println("Zero write no: " + zeroByteWrites);
//ok time to worry... over 50 zero writes and the buffer is not completly
//written.. so let an observer check the connection
if(zeroByteWrites > 50) {
System.out.println("Check conn via observer");
ByteBuffer bufferCopy = ByteBuffer.allocate(buffer.capacity());
bufferCopy.put(buffer);
// add it to the blacklist so the selector can not select to write anymore
blackList.add(key);
new Thread(new ConnectionObserver(key, bufferCopy)).start();
break;
}
}
}
buffer.clear();
key.interestOps(SelectionKey.OP_READ);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void accept(SelectionKey key) {
try {
SocketChannel client = serverChannel.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ, new ConnectionInfo());
System.out.println("Accepted on OP_READ: "
+ client.socket().getInetAddress().toString());
} catch (IOException e) {
e.printStackTrace();
}
}
public void shutdown(){
shutdown = true;
}
//Utils classes -----------------------------------------------------------------------------------
private class ConnectionInfo {
private long timestamp;
public ConnectionInfo() {
timestamp = System.currentTimeMillis();
}
public void reset(){
timestamp = System.currentTimeMillis();
}
public long getTimestamp() {
return timestamp;
}
public long getIdleTime() {
return System.currentTimeMillis() - timestamp;
}
}
private class ConnectionObserver implements Runnable{
long timeout;
long idletime;
SelectionKey key;
ByteBuffer bufferRemaining;
boolean end = false;
public ConnectionObserver(SelectionKey key, ByteBuffer bufferRemaining) {
this(key, bufferRemaining, 2000L);
}
public ConnectionObserver(SelectionKey key, ByteBuffer bufferRemaining, long timeout){
this(key, bufferRemaining, timeout, 5);
}
public ConnectionObserver(SelectionKey key, ByteBuffer bufferRemaining, long timeout, long idletime){
this.key = key;
this.bufferRemaining = bufferRemaining;
this.timeout = timeout;
this.idletime = idletime;
}
@Override
public void run() {
SocketChannel channel = (SocketChannel) key.channel();
long time = System.currentTimeMillis();
while(!end){
try {
System.out.println((System.currentTimeMillis() - time) + " msecs passed!");
//check if we are at the timeout
if((System.currentTimeMillis() - time) > timeout){
//if so... we shut the connection
key.cancel();
channel.close();
System.err.println("Client canceled by observer: Timeout!");
terminate();
} else {
//we try to write the remaining buffer again
System.err.println("Try to write...");
int tmpBytes = channel.write(bufferRemaining);
Thread.sleep(idletime);
//if we've done all the work -> go back to reading ops and terminate the observer
if(!bufferRemaining.hasRemaining()){
key.interestOps(SelectionKey.OP_READ);
key.channel().register(key.selector(), SelectionKey.OP_READ);
terminate();
}
}
} catch (IOException e1) {
e1.printStackTrace();
} catch (InterruptedException e) {e.printStackTrace();}
}
}
private void terminate() {
end = true;
}
}
public static void main(String[] args) {
NioServer server = new NioServer(8888, "localhost");
new Thread(server).start();
}
}
Bin für Anregungen dankbar.
Mfg Alex
Zuletzt bearbeitet: