Я несколько раз пытаюсь использовать несколько разных методов, чтобы заставить мой пользовательский прокси работать, и единственным способом, которым я был до сих пор, является использование HttpClient от Apache. Однако, ради познания, я задавался вопросом, почему у меня возникают проблемы с моей собственной реализации прокси-ручки ниже:Проблемы с входным/выходным потоком прокси в Java
public void processProxyRequest (Socket client, String request) throws Exception {
if (!request.equals("")) {
String[] requestHeaders = request.split("\\r\\n");
Pattern p = Pattern.compile("([A-Z]*)\\s*([^:\\/]*):\\/\\/([^\\s]*)\\s*(?:HTTP.*)");
Matcher m = p.matcher(requestHeaders[0]);
if (m.matches()) {
String method = m.group(1).toUpperCase();
String proto = m.group(2).toLowerCase();
String[] requestInfo = m.group(3).split("\\/", 2);
String host = requestInfo[0];
host = (host.split("\\.").length < 3) ? "www." + host : host;
String page = "/";
if (requestInfo.length == 2 && !requestInfo[1].equals("")) {
page += requestInfo[1];
}
int remotePort = 80;
if (proto.equals("https")) {
remotePort = 443;
}
else if (proto.equals("ftp")) {
remotePort = 21;
}
this.sendAndReceive(client, request, host, remotePort);
}
}
}
public void sendAndReceive (Socket client, String request, String host, int port) throws Exception {
Socket target = new Socket(host, port);
System.out.println("Connected to server");
ByteArrayInputStream inStream = new ByteArrayInputStream(request.getBytes());
this.inToOut(inStream, target.getOutputStream());
System.out.println("Sent");
this.inToOut(target.getInputStream(), client.getOutputStream());
System.out.println("Received");
target.close();
}
public void inToOut (InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024]; // Adjust if you want
int bytesRead;
System.out.println("reading");
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
}
В двух словах (и игнорируя мой заголовок запроса синтаксического анализа недостатков), приведенный выше код компилируется и однако, метод inToOut()
, похоже, немного борется и блокируется во время ввода.read(), и я не слишком уверен в этом. Я действительно знаю, что исходный сокет, который я передаю, действителен и открыт без ошибок. Кроме того, System.out
в функции inToOut() печатает «чтение», но никогда не проходит мимо части read()
.
Благодарим за любые предложения!
Я понимаю, поэтому строка запроса на самом деле уже передана в метод processRequest() для начала. Я сделал несколько дополнительных синтаксических разборок для более поздних функций регистрации, тогда как я хотел бы отслеживать определенные свойства заголовка запроса и ответа. Что касается «простого» копирования байтов взад и вперед, что, по-видимому, неверно в приведенном выше? Я был уверен, что это то, что я делал, копируя поток в потоке от клиента к выходному потоку цели, а затем от целевой в потоке к клиенту в потоке. И все же, никакого успеха. – jerluc
Невозможно прокомментировать, не увидев код копирования. Если вы не используете NIO, вам нужно два потока на соединение, один для копирования в каждом направлении. Тот же код для обоих, конечно, они просто читают и записывают байты до EOS. – EJP
Уже существует код, а именно метод 'inToOut()', который пытается скопировать байты из входного потока клиента в выходной поток целевого сервера. Конечно, я не смог разместить их в отдельных потоках, но сейчас я попытался использовать потоки, а затем попытался использовать NIO, но обе попытки, похоже, записывают данные на целевой сервер (для моих тестов просто google.com), но они всегда замерзают, когда пытаются прочитать ответ. – jerluc