나는 사용자 정의 프록시를 작동시키는 데 몇 가지 다른 방법을 시도해 왔으며, 지금까지 할 수 있었던 유일한 방법은 Apache의 HttpClient를 사용하는 것이다. 그러나 알을 위해, 내가 아래에있는 내 자신의 프록시 핸들 구현에 문제가 있어요 왜 궁금 : 간단히 말해서자바에서 프록시 입출력 스트림 문제
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()
메서드가 약간 어려움을 겪고 input.read() 중에 잠기는 것처럼 보입니다. 그 이유는 확실하지 않습니다. 내가 전달하는 원래 소켓이 유효하고 오류없이 열렸다는 사실을 알고 있습니다. 또한 inToOut() 함수의 System.out
은 "읽기"를 인쇄하지만 read()
부분을 지나치지 않습니다.
의견을 보내 주셔서 감사합니다.
나는 requestline이 실제로 processRequest() 메소드에 이미 전달되어 있기 때문에 이해합니다. 특정 요청 및 응답 헤더 속성을 추적하고 싶지만 나중에 기능을 로깅하기 위해 몇 가지 추가 구문 분석을 수행했습니다. 앞뒤로 바이트의 "간단한"복사에 관해서는, 위의 잘못된 것? 나는 그것이 클라이언트의 스트림을 대상의 아웃 스트림으로 복사 한 다음 스트림의 대상에서 스트림의 클라이언트로 복사하여 수행 한 작업임을 확신했습니다. 그러나 여전히 성공하지 못했습니다. – jerluc
복사 코드를 보지 않고도 댓글을 달 수 없습니다. NIO를 사용하지 않는 한 연결 당 두 개의 스레드가 필요합니다. 각 스레드는 각 방향으로 복사해야합니다. 두 가지 모두 동일한 코드입니다. EOS 때까지 바이트를 읽고 씁니다. – EJP
이미 코드가 있습니다. 즉, 클라이언트의 입력 스트림에서 대상 서버의 출력 스트림으로 바이트를 복사하려고 시도하는'inToOut()'메소드가 있습니다. 물론 두 스레드를 별도의 스레드에 배치하지 못했지만 지금은 스레드를 사용하려고 시도한 다음 나중에 NIO를 사용하려고 시도했지만 두 방법 모두 대상 서버에 데이터를 쓰는 것 같습니다 (테스트의 경우 google.com 만 사용).)하지만 응답을 읽으려고하면 항상 고정됩니다. – jerluc