0

Немного со своими сокетами. Я обнаружил следующую проблему. Эта программа:java.net.Socket constructor выбрасывает исключение Socket, если используется версия с 4 параметрами, но не с 2 версией параметра

public class TestSocket { 

    private static final String remoteHost = "gmail-smtp-in.l.google.com"; 
    private static final int port = 25; 

    public static void main(String[] args) throws UnknownHostException, IOException { 
     System.out.println("Remote: " + InetAddress.getByName(remoteHost)); 
     System.out.println("Local: " + InetAddress.getByName("localhost")); 

     Socket socket = new Socket(InetAddress.getByName(remoteHost), port, InetAddress.getByName("localhost"), 0); 


     OutputStream out = socket.getOutputStream(); 
     InputStream in = socket.getInputStream(); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 
     PrintWriter pw = new PrintWriter(out); 
     System.out.println("Server --> " + reader.readLine()); 
     pw.println("helo localhost"); 
     System.out.println("Sent 'helo localhost'"); 
     socket.close(); 
    } 

} 

бросает исключение java.net.SocketException: Network is unreachable: connect в соответствии с конструктором сокета. Однако после попытки с помощью telnet и netcat я проверил, что сервер доступен и отправляет данные. Так что это проблема с конструктором. Когда я изменить его на следующее программа работает и имеет возможность подключения:

Socket socket = new Socket(InetAddress.getByName(remoteHost), port); 

Я не могу понять, что делает разницу. Разве этот второй конструктор также не должен связываться с эфемерным портом на локальном хосте, например, первым, когда передается 0 в качестве порта? Почему один работает, а другой нет?

Редактировать: с помощью Java 1.8.0_112 на ОС Windows 10.

+0

Это именно то, что делает вторая линия в главном. Он возвращает localhost/127.0.0.1 – joanlofe

+0

Могу ли я спросить, почему этот вопрос был проголосован? – joanlofe

ответ

2

общественное гнездо (InetAddress хост, Int порт, интерфейс InetAddress, внутр локальный_порт) бросает IOException

Это гнездо Соединяет на хост и порт, указанные в первых двух аргументах. Он соединяется с локальным сетевым интерфейсом и портом, указанным двумя последними аргументами.

Итак, вы пытаетесь подключиться к общедоступному адресу с вашего локального хоста, что не имеет никакого смысла. Последние 2 аргумента этого конструктора требуют выбора локального интерфейса для подключения.


Использование регистра объяснено для выбора этого способа создания сокета:

Предположим, вы пишете программу периодически дамп журналы ошибок на принтер или отправить их на внутренний почтовый сервер. Вы должны убедиться, что используете сетевой интерфейс, обращенный внутрь, вместо сетевого интерфейса. Итак, в таких случаях вы выберете этот способ построения сокета.

+0

Отличное объяснение, теперь я понимаю проблему. Большое спасибо! – joanlofe

+0

Если вы хотите подключиться к 127.0.0.1, вы все равно будете использовать конструктор с двумя аргументами и пусть система выберет локальную привязку для себя. Единственный случай использования для четырех аргументов, с которыми я когда-либо сталкивался, - это когда для IP-маршрутизации требуется небольшая помощь в случае VPN. – EJP