http 클라이언트 요청을 디버그하려고합니다. 연결이 이루어질 때 사용 된 로컬 포트 번호를 가져와야합니다. HttpClientContext를 사용하여 연결을 가져오고 연결이 성공하면 로컬 포트를 검색 할 수 있습니다. 그러나 IOException이 발생하는 경우 로컬 포트 번호를 검색 할 때 ConnectionShutdownException이 발생합니다. 오류 발생시 모든 http 요청에 대해 로컬 포트 번호를 얻을 수있는 방법에 대한 단서.Apache InternalHttpClient : 로컬 포트 번호 확인
답변
이것은 HTTPClient 4.0.1 (나와 함께있는 마지막 버전) 용입니다. 간단한 하나의 라이너를 찾지 못했습니다 ...
소켓을 로컬 호스트/포트에 실제로 바인드하고 원격 호스트/포트에 연결하는 부분은 당연히 SocketFactory입니다. HTTPClient에서 소켓 팩토리는 SchemeRegistry에 연결되며, 연결 관리자는 차례로 연결 관리자에 속합니다. HTTPClient의 SocketFactory는 javax.net.SocketFactory가 아니라 그러한 객체를 감싸는 래퍼입니다.
물론SchemeRegistry schRgstr = new SchemeRegistry();
Scheme httpScheme = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
schRgstr.register(httpScheme);
는 org.apache.http.conn.scheme.SocketFactory는 인터페이스입니다, 그래서 당신은이 편리 올 것이다 당신이 특히 원하는 무엇이든 할 그것을 장식 할 수 있습니다 : 당신은 너무 같은 방식을 정의 .
소켓 팩토리를 호출하는 httpclient의 부분은 ClientConnectionOperator
(인터페이스이기도 함)이라고합니다. 이 객체는 실제로 클라이언트가 아닌 이 아닌 연결 관리자와 연결되어 있습니다. 당신이 연결 연산자를 정의하려는 경우, 당신은, 예를 들어, 같은 (익명 클래스)도 연결 관리자를 오버라이드 (override) 할 수 있습니다 그래서 :
-
:
- 연결 관리자가 지금 연결이 필요할 때 운영자에게
createConnection
을 호출합니다 (기본적으로 실제 소켓을 보유 할 내부 개체를 만들지 만 아무것도하지 않습니다). - 은 또한 길을 따라 그 다음,
openConnection
대해서 openConnection가
SocketFactory
로 이동하고 새로운 소켓을 요청 호출과 같이 연결을 시도sock = sf.connectSocket(sock, target.getHostName(), schm.resolvePort(target.getPort()), local, 0, params);
(여기서, SF는 "HttpClient를 소켓 팩토리"입니다)
이 호출이 실패하면 예외가 발생하고 더 많은 정보에 액세스 할 수 없습니다. 우리는 그걸로 돌아갈거야.
connectSocket이 작동하는 경우 연결 연산자에서
prepareSocket
메서드가 호출됩니다. 그래서, 당신은 방법을 무시하고 상황에 포트 정보를 넣어 (또는 아무것도 당신 공상) :@Override protected void prepareSocket(Socket sock, HttpContext context, HttpParams params) throws IOException { super.prepareSocket(sock, context, params); context.setAttribute("LOCAL PORT INTERCEPTOR", sock.getLocalPort()); }
ThreadSafeClientConnManager connMngr = new ThreadSafeClientConnManager(httpParams, schRgstr) {
protected ClientConnectionOperator createConnectionOperator(SchemeRegistry schreg) {
return new YourConnectionOperator(schreg);
};
};
소켓의 라이프 사이클 모델과 같이 간다
당신이 HttpClient를 호출 할 때, 그래서 전달 사용되는 HttpContext를 예 다른 예외 때문에 나중에 호출이 실패하더라도이를 액세스 할 수 있습니다. 당신이 당신의 전화를 걸 때, 그래서 그것을 만들 :
HttpContext ctx = new BasicHttpContext();
HttpGet get = new HttpGet(targetUrl.getUrl());
HttpResponse resp = client.execute(get, ctx);
를이 코드에서, 클라이언트는 5 단계로까지 갈 수 있다면, 당신은 예외가 나중에 발생하는 경우에도 포트 정보에 액세스 할 수 있습니다 (연결 드롭 아웃 , 시간 초과, 유효하지 않은 HTTP 등).가는
더
이 모든 어두운 영역이 여전히있다 : 전화 4 단계에서 실패하는 경우 (소켓의 실제 개방, 같은 대상 호스트 이름을 해결하는 동안 당신은 DNS 오류가있는 경우) ... 나는이 사건이 실제로 당신에게 흥미로운 지 확신하지 못합니다. (왜 그런지는 알 수 없습니다.) 그것을 다루는 것을 보는 것이 "지저분 해"지기 시작하면, 여러분은 이것을 필요로하거나 그렇지 않은지 정말로 고려해야합니다.
우리는 정말 깊은 우선 작업을 시작해야하며, 많은 작업이 필요합니다. 그 중 일부는 아주 좋은 디자인을 고려하지 않았습니다.
HTTPClient 작성자가 필요한 정보를 얻기 위해 재정의 할 수있는 필요한 메서드를 제공하지 않아 복잡성이 발생합니다. 소켓 공장 내부, 흥미로운 점은 다음과 같습니다
sock = createSocket();
InetSocketAddress isa = new InetSocketAddress(localAddress, localPort);
sock.bind(isa);
// go on and connect to the server
// like socket.connect...
, 로컬 및 소켓 열리는의 서버 측을 분할 재정의 할 방법은 없습니다 그래서 모든 소켓 예외는 서버 측에서 발생하는 경우, 당신을 소켓 인스턴스에 대한 액세스가 손실되고 로컬 포트 정보가 사라집니다.
우리가 할 수있는 엔트리 포인트가 하나 있기 때문에 모든 것이 손실되지 않습니다 : createSocket 메소드! 기본 구현은
public Socket createSocket() {
return new Socket();
}
입니다 그러나 소켓 최종 클래스 아니므로, 당신은 ... 그것으로 재생할 수 있습니다!
public Socket createSocket() {
return new Socket() {
@Override
public void bind(SocketAddress bindpoint) throws IOException {
super.bind(bindpoint);
// get the local port and give the info back to whomever you like
}
};
}
문제는 다음과 같습니다 (우리는 익명의 하위 클래스를 만들 수 있기 때문에)이 일반 소켓 작동하지만, 당신은 단순히이 경우에 소켓을 실체화 할 수 없기 때문에 이것은, 당신이해야 할, HTTPS 작동하지 않습니다 :
return (SSLSocket) this.javaxNetSSLSocketFactory.createSocket();
그런 경우 익명 하위 클래스를 만들 수 없습니다. 그리고 Socket은 인터페이스가 없기 때문에 프록시로 꾸미기조차 할 수 없습니다. 그래서 (혹독한 코드도) SSLSocket에 랩핑하고 위임하는 Socket 서브 클래스를 만들 수 있습니다. 그러나 그것은 필사적입니다.
그래서 정리 시간.
서버에 연결되어있는 소켓에 대해서만 신경 쓰면 솔루션은 매우 간단합니다.
ConnectionOperator
을 덮어 쓰는 사용자 지정 ConnectionManager
에서 우리가 작성한 체계 레지스트리가 사용됩니다. 운영자가 재정의하는 메서드는 prepareSocket
이며 포트 정보와 함께 전송되는 요청의 HttpContext
을 간단히 업데이트 할 수 있습니다. 모든 것이 잘되면 정보를 쉽게 찾을 수있는 방법입니다.
절대로, 연결되어 있지 않은 (내가 제한적으로 사용한다고 주장하는) 소켓에 할당 된 로컬 포트를 신경 쓰고 싶다면, 더 깊게 갈 필요가 있습니다.
당사의 SchemeRegistry
은 맞춤 SocketFactories
을 갖도록 설계되어야합니다. 이것들은 아마도 데코레이터 또는 디폴트 것이어야합니다 ...createSocket
오버라이드 (override) 메소드를 사용하면 로컬 포트의 바인딩을 가로 채고 (ConcurrentMap<Socket, Integer>
또는 ThreadLocal
에 저장) 'connectSocket'을 오버라이드하여 발생할 수있는 모든 예외를 트랩하고 다시 브로드 캐스팅 할 수 있습니다 로컬 포트 정보를 보유 할 수있는 자체 예외 유형으로 랩핑합니다. 그런 식으로 예외를 통과해도 클라이언트를 호출 할 때 원인 체인을 확인하면 포트 데이터를 찾을 수 있습니다. 예외가 발생하지 않으면 인스턴스/스레드 로컬을 정리하거나 매핑합니다.
- 1. 포트 번호 80의 Apache 서버
- 2. 소켓의 로컬 포트 번호 받기
- 3. 서버 변수의 로컬 호스트 및 포트 번호
- 4. 소켓 프로그래밍 : 로컬 호스트로 8888 : 포트 번호
- 5. 클라이언트가 바인딩 된 TCP 포트 번호 확인
- 6. 박쥐 파일을 사용하여 Windows에서 포트 번호 확인
- 7. 포트 번호
- 8. Linux에서 포트 가용성 확인
- 9. 자바 스크립트의 document.domain와 포트 번호
- 10. Wordpress 이미지의 포트 번호 URL
- 11. 진행 ODBC 포트 번호 10.2a
- 12. USB 포트 번호
- 13. CVS의 기본 포트 번호
- 14. C 번호, 시리얼 포트
- 15. 서버의 포트 번호
- 16. Javamail 포트 번호 변경
- 17. 프로토콜 및 포트 번호
- 18. PingFederate의 포트 번호 변경
- 19. 하나 개의 포트 번호
- 20. Kaltura 포트 번호?
- 21. Windows.Devices.Enumeration.DeviceInformation의 COM 포트 번호
- 22. JQuery, ajax, 포트 번호
- 23. 포트 번호 및 URL의
- 24. OpenJMS - 클라이언트 포트 번호
- 25. 포트 Apache 및 ExpressJS
- 26. 크롬 DevTools로 포트 포워딩 높은 포트 번호
- 27. Apache Mina : 원격 클라이언트가 연결된 로컬 포트 가져 오기
- 28. 번호 확인
- 29. 원격 시스템의 포트 가용성 확인
- 30. URL에서 정규식 추출 번호 (포트 번호 제외)
'ConnectionShutdownException'은 연결이 설정되지 않았거나 연결을 종료시키는 어떤 문제로 인해 연결이 현재 존재하지 않음을 의미합니다. 연결이 없으면 열린 포트가 없으며 정의 상 포트 번호가 없습니다. – Baldy