В сегодняшних сетевых средах, строго корпоративных, разработчикам приложений приходится иметь дело с прокси практически так же часто, как и системным администраторам. В некоторых случаях приложение должно использовать системные настройки по умолчанию, в других случаях будет полезно иметь очень жесткий контроль над тем, что проходит через какой прокси, и где-то посередине большинство приложений будут в восторге от делегирования решения своим пользователям, предоставив им графический интерфейс для настройки параметров прокси, как это имеет место в большинстве браузеров.
Прокси-серверы действуют как интерфейсы между клиентскими приложениями и другими серверами. На предприятии мы часто используем их, чтобы обеспечить контроль над контентом, потребляемым пользователями, обычно за пределами сети.
Подходы:
Мы выясним два способа подключения через прокси-серверы в java, а именно:
Java демонстрирует набор системных свойств, которые можно использовать для настройки поведения всей JVM. Этот «универсальный» подход зачастую проще всего реализовать, если он подходит для конкретного случая использования. Мы можем установить необходимые свойства из командной строки во время вызова JVM. В качестве альтернативы мы также можем определить их с помощью System.setProperty () во время выполнения. Вот как их определить с помощью командной строки, как показано ниже:
Мы можем определить прокси в командной строке, минуя параметры как системные свойства:
java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8080 com.geeksforgeeks.networking.proxies.CommandLineProxyDemo
При запуске процесса таким образом мы можем просто использовать openConnection () для URL без дополнительной работы:
URL url = new URL(RESOURCE_URL); URLConnection con = url.openConnection();
Если при использовании командной строки возникают проблемы, есть другой способ сделать это, используя метод System.setProperty (). Для настройки прокси.
System.setProperty(“http.proxyHost”, “127.0.0.1”); System.setProperty(“http.proxyPort”, “8080”); URL url = new URL(RESOURCE_URL); URLConnection con = url.openConnection(); // …
Если мы затем вручную отключим соответствующие системные свойства, прокси больше не будет использоваться:
System.setProperty(“http.proxyHost”, null);
Теперь вместе с этим возникают ограничения глобальной конфигурации, описанные ниже.
Таким образом, в качестве альтернативы Proxy API более эффективен и обеспечивает больший контроль над конфигурацией прокси. В качестве альтернативы Proxy API обеспечивает более детальный контроль над конфигурацией прокси. Это рождает другой подход, который через Proxy API.
Класс Proxy дает нам гибкий способ настройки прокси для каждого соединения. Если существуют какие-либо существующие настройки прокси для всей JVM, настройки прокси на основе подключения с использованием класса Proxy переопределят их. Вот три типа прокси, которые мы можем определить по типу прокси:
(A) Использование прокси-сервера HTTP
Чтобы использовать HTTP-прокси, мы сначала оборачиваем экземпляр SocketAddress с помощью Proxy и типа Proxy.Type.HTTP. Затем мы просто передаем экземпляр Proxy в URLConnection.openConnection ():
URL weburl = new URL(URL_STRING); Proxy webProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(“127.0.0.1”, 8080)); HttpURLConnection webProxyConnection = (HttpURLConnection) weburl.openConnection(webProxy);
Теперь мы подключимся к URL_STRING, но затем направим это соединение через прокси-сервер, расположенный по адресу 127.0.0.1:8080.
У нас может возникнуть потребность напрямую подключиться к хосту. В этом случае мы можем явно обойти прокси, который может быть настроен глобально, с помощью статического экземпляра Proxy.NO_PROXY. По сути, API создает для нас новый экземпляр Proxy, используя Proxy.Type.DIRECT в качестве типа:
HttpURLConnection directConnection = (HttpURLConnection) weburl.openConnection(Proxy.NO_PROXY);
Прокси-сервер Socks работает аналогично варианту HTTP при работе с URLConnection. В прокси Socks сначала мы оборачиваем экземпляр SocketAddress прокси, используя тип Proxy.Type.SOCKS. После этого экземпляр Proxy передается в URLConnection.openConnection.
Proxy socksProxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(“127.0.0.1”, 1080)); HttpURLConnection socksConnection = (HttpURLConnection) weburl.openConnection(socksProxy);
Также можно использовать прокси-сервер SOCKS при подключении к сокету TCP. Сначала мы используем экземпляр Proxy для создания Socket. После этого мы передаем целевой экземпляр SocketAddress в Socket.connect () следующим образом:
Socket proxySocket = new Socket(socksProxy); InetSocketAddress socketHost = new InetSocketAddress(SOCKET_SERVER_HOST, SOCKET_SERVER_PORT); proxySocket.connect(socketHost);
Пример:
// Java-программа для создания простого прокси-сервера // Импорт классов ввода вывода import java.io.*; // Импорт import java.net.*; public class SimpleProxyServer { public static void main(String[] args) throws IOException { try { String host = "Ваш прокси сервер"; int remoteport = 100; int localport = 111; // Печать сообщения о запуске System.out.println("Starting proxy for " + host + ":" + remoteport + " on port " + localport); // И начните запускать сервер runServer(host, remoteport, localport); // never returns } catch (Exception e) { System.err.println(e); } } /** * запускает однопоточный прокси-сервер на указанном * локальном порту. Он никогда не возвращается. */ public static void runServer(String host, int remoteport, int localport) throws IOException { // Create a ServerSocket to listen for connections // with ServerSocket ss = new ServerSocket(localport); final byte[] request = new byte[1024]; byte[] reply = new byte[4096]; while (true) { Socket client = null, server = null; try { // Дождитесь подключения на локальном порту client = ss.accept(); final InputStream streamFromClient = client.getInputStream(); final OutputStream streamToClient = client.getOutputStream(); // Установите соединение с реальным сервером. // Если мы не можем подключиться к серверу, // отправьте сообщение об ошибке клиенту, отключитесь // и продолжайте ждать подключения. try { server = new Socket(host, remoteport); } catch (IOException e) { PrintWriter out = new PrintWriter(streamToClient); out.print( "Proxy server cannot connect to " + host + ":" + remoteport + ":\n" + e + "\n"); out.flush(); client.close(); continue; } // Получить потоки сервера. final InputStream streamFromServer = server.getInputStream(); final OutputStream streamToServer = server.getOutputStream(); // поток для чтения запросов клиента // и передачи их на сервер. Отдельный // поток для асинхронного. Thread t = new Thread() { public void run() { int bytesRead; try { while ((bytesRead = streamFromClient.read( request)) != -1) { streamToServer.write( request, 0, bytesRead); streamToServer.flush(); } } catch (IOException e) { } // клиент закрыл соединение // с нами, поэтому закройте наше // соединение с сервером. try { streamToServer.close(); } catch (IOException e) { } } }; // Запустите поток запросов от клиента к серверу // запуск t.start(); // Прочитайте ответы сервера // и передайте их обратно клиенту int bytesRead; try { while ((bytesRead = streamFromServer.read(reply)) != -1) { streamToClient.write(reply, 0, bytesRead); streamToClient.flush(); } } catch (IOException e) { } // Сервер закрыл свое соединение с нами, // поэтому мы закрываем наше соединение с нашим клиентом. streamToClient.close(); } catch (IOException e) { System.err.println(e); } finally { try { if (server != null) server.close(); if (client != null) client.close(); } catch (IOException e) { } } } } }
Вывод:
Заключение
В соответствии с выводом мы выясняем, как работать с прокси-серверами в ядре Java. Сначала мы рассмотрели более старый, более глобальный стиль подключения через прокси-серверы с использованием системных свойств. Затем мы увидели, как использовать класс Proxy, который обеспечивает детальный контроль при подключении через прокси-серверы.