Заинтересовался сабжем. Дабы проверить - написал такой быдлокод, который делает (должен делать) следующее:
1) Сервер ждет соединений на порту 10222
2) Клиент подключается к серверу, узнает порт своего исходящего соединения и поднимает на этом порту свой сервер
3) Сервер пытается установить соединение с IP и портом создавшим это соединение (здесь IP и порт вашего провайдера, который, теоретически, должен нисмотря ни на что ссылаться на ваш внутренний IP и порт, это соединение открывший)
К сожалению, при запуске клиента за NAT получаю Connection Refused
Часть 1 - серверная сторона:
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleServer {
ServerSocket ss;
public void startServer() throws IOException{
ss = new ServerSocket(10222);
System.out.println("Сервер запущен по адресу: " + ss.getLocalSocketAddress());
}
public void stopServer() throws IOException{
ss.close();
}
public void waitConnection() throws IOException, InterruptedException{
Socket s = ss.accept();
int remotePort = s.getPort();
InetAddress host = s.getInetAddress();
System.out.println("Пытаюсь установить соедиение с " + host.getHostAddress() + " на порт: " + remotePort);
//попытка установления соединения с клиентом, который в этот момент ожидает соединения
Thread.sleep(1000);
Socket socket = new Socket(host, remotePort);
System.out.println("Соединение установлено, отправляем тестовые данные");
//Отправка данных
OutputStream os = socket.getOutputStream();
os.write("Hello, client!".getBytes());
s.close();
}
public static void main(String[] args) throws InterruptedException, IOException{
SimpleServer ss = new SimpleServer();
ss.startServer();
ss.waitConnection();
ss.stopServer();
}
}
Часть 2 - сторона клиента:
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleClient implements Runnable{
SimpleClient(){}
//
SimpleClient(Socket socket){
this.socket = socket;
Thread t = new Thread(this);
t.start();
}
Socket socket;
String server = "192.168.10.10";
int port;
public void connect(){
try {
//Подключаемся к серверу
Socket socket = new Socket(server, 10222);
port = socket.getLocalPort();
System.out.println("Обнаружен локальный порт: " + port);
socket.setReuseAddress(true);
//Создаем свой сервер на порту, использованному при исходящем соединении
ServerSocket serverSocket = new ServerSocket(port);
//Ждем соединений с созданного сервера
while(true){
System.out.println("Ожидание соединения на порту: " + port);
Socket gotSocket = serverSocket.accept();
System.out.println("Получено соединение");
new SimpleClient(gotSocket); //Запустить поток, который будет читать сокет
}
} catch (IOException e) {
e.printStackTrace();
}
}
//Чтение данных из сокета
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
int c;
while( (c = is.read()) != -1 ){
System.out.print((char) c);
}
} catch (IOException e) {
System.err.println("Ошибка ввода вывода");
}
}
public static void main(String[] args){
new SimpleClient().connect();
}
}