java.net 수정 방법Socket Exception:부러진 파이프?
post method를 사용하여 url을 호출하여 파라미터를 게시하기 위해 apache commons http client를 사용하고 있으며, 아래와 같은 에러가 거의 발생하지 않습니다.
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
at org.apache.commons.httpclient.methods.ByteArrayRequestEntity.writeRequest(ByteArrayRequestEntity.java:90)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
이 예외의 원인과 디버깅 방법을 제안할 수 있습니까?
원인은 다음과 같습니다.
- 대부분의 경우, 다른 한쪽이 이미 접속을 닫았을 때 접속에 쓰는 것.
- 일반적으로 피어는 자신의 엔드에서 이미 보류 중인 모든 데이터를 읽지 않고 연결을 종료합니다.
따라서 두 경우 모두 애플리케이션 프로토콜이 제대로 정의되거나 구현되지 않았습니다.
여기서는 설명하지 않지만, 피어가 접속을 적절히 닫지 않고 신중하게 리셋을 실행하는 세 번째 이유가 있습니다.
이 경우 앱 서버에서 로드 테스트를 수행하는 동안 이 문제가 발생했습니다.이 문제는 JVM의 메모리가 부족하기 때문에 메모리를 추가해야 한다는 것을 알게 되었습니다.이것으로 문제가 해결되었다.
이러한 오류가 발생하면 JVM에서 사용할 수 있는 메모리를 늘리거나 메모리 사용량을 모니터링해 보십시오.
Socket Exception:파이프가 끊어진 원인은 코드가 연결을 읽거나 쓰는 동안 '다른 쪽 끝'(클라이언트 또는 서버)이 연결을 닫았기 때문입니다.
이는 응용 프로그램 제어 외부에서 클라이언트 또는 서버로부터 트래픽을 수신하는 클라이언트/서버 응용 프로그램에서 매우 일반적인 예외입니다.예를 들어 클라이언트는 브라우저입니다.브라우저가 Ajax 콜을 발신하거나 사용자가 페이지 또는 브라우저를 닫기만 하면 모든 통신이 예기치 않게 끊어질 수 있습니다.기본적으로 이 오류는 상대방이 애플리케이션을 종료할 때마다 나타나며, 사용자가 예상하지 못했던 오류입니다.
애플리케이션에서 이 예외가 발생할 경우 IO(Input/Output)가 발생하는 코드를 확인하고 IOException을 포착하기 위해 코드를 try/catch 블록으로 랩해야 합니다.그러면 이 반유효한 상황을 어떻게 처리할지는 사용자에게 달려 있습니다.
의 경우,는 '아, 아, 아, 아, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네, 네.HttpMethodDirector.executeWithRetry
으로 랩되어 해 주십시오 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」
디버깅/트레이스레벨 이외에서는 SocketException-Broken Pipe 고유의 오류를 로깅하지 않도록 강력히 권장합니다.그렇지 않으면 로그를 채워 DOS(서비스 거부) 공격의 한 형태로 사용할 수 있습니다.이 일반적인 시나리오에서 응용 프로그램을 강화하고 네거티브 테스트해 보십시오.
열려 있는 모든 스트림과 연결을 적절하게 닫아야 하기 때문에 다음 번에 urlConnection 개체를 사용하려고 해도 오류가 발생하지 않습니다.예를 들어, 아래의 코드 변경으로 오류가 수정되었습니다.
이전:
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("Some text");
bw.close();
out.close();
그 후:
OutputStream os = urlConnection.getOutputStream();
OutputStream out = new BufferedOutputStream(os);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("Some text");
bw.close();
out.close();
os.close(); // This is a must.
FTP 서버를 통해 데이터 다운로드 기능을 구현하여 다운로드를 재개하는 동안 동일한 예외를 발견하였습니다.이 예외를 해결하려면 항상 이전 세션에서 연결을 끊고 클라이언트의 새 인스턴스 및 서버와의 새 연결을 생성해야 합니다.이 방법은 HTTP Client에도 도움이 될 수 있습니다.
특정 TCP에서 리슨하는 간단한 자바 애플리케이션을 개발하면서 같은 문제가 발생하였습니다.가 없었습니다만, 때, 에러로 이 끊어진 을 알 수 .socket write exception
.
조사 후, 나는 나의 문제를 해결할 수 있는 해결책을 찾았다.이 질문이 꽤 오래되었다는 것은 알지만, 누군가가 유용하다고 생각할 수 있도록 제 해결책을 공유하고 싶습니다.
서버 소켓을 선택합니다.Javadoc에서 읽은 바로는 50개의 보류 소켓으로 기본 제한이 있습니다.다른 연결을 열려고 하면 연결이 거부됩니다.솔루션은 서버 측에서 이 기본 구성을 변경하는 것만으로 구성됩니다.예에서는 포트에서 .10_000
" " " " " 를 .200
보류 중인 소켓
new Thread(() -> {
try (ServerSocket serverSocket = new ServerSocket(10_000, 200)) {
logger.info("Server starts listening on TCP port {}", port);
while (true) {
try {
ClientHandler clientHandler = clientHandlerProvider.getObject(serverSocket.accept(), this);
executor.execute(clientHandler::start);
} catch (Exception e) {
logger.error(e.getMessage());
}
}
} catch (IOException | SecurityException | IllegalArgumentException e) {
logger.error("Could not open server on TCP port {}. Reason: {}", port, e.getMessage());
}
}).start();
Server Socket의 Javadoc에서 제공:
착신 접속 표시(접속 요구)의 최대 큐 길이는 backlog 파라미터로 설정됩니다.큐가 꽉 찼을 때 연결 표시가 나타나면 연결이 거부됩니다.
배포된 파일이 올바른 RMI 방법으로 업데이트되지 않은 것이 문제일 수 있습니다.RMI 인터페이스에 갱신된 파라미터 또는 클라이언트에 없는 갱신된 데이터 구조가 있는지 확인합니다.또는 RMI 클라이언트에 서버 버전과 다른 파라미터가 없는지 확인합니다.
이것은 단지 교양있는 추측일 뿐이다.서버 응용 프로그램의 클래스 파일을 다시 배포하고 다시 테스트한 후 "파이프 고장" 문제가 사라졌습니다.
위의 답변은 그 이유를 설명합니다.java.net.SocketException: Broken pipe
: 다른 쪽 끝은 연결을 닫았습니다.처음 접했을 때의 경험을 공유하겠습니다.
- 고객의 요구에 따라
Content-Type
헤더가 요구 본문보다 크게 잘못 설정되어 있다(실제로 본문은 전혀 없었다). - tomcat 소켓의 하단 서비스가 해당 크기의 본문 데이터를 기다리고 있었습니다(http는 캡슐화를 통해 전달을 보증하는TCP 상에 있습니다.
- 60초 경과 시 Tomcat은 타임아웃 예외를 슬로우합니다.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception java.net.SocketTimeoutException: null
- 타임아웃 예외로 인해 클라이언트는 상태 코드 500의 응답을 수신합니다.
- 클라이언트의 접속을 종료합니다(응답이 수신되기 때문입니다).
- Tomcat이 던지다
java.net.SocketException: Broken pipe
고객이 닫았기 때문입니다.
timeout 예외로 인해 접속이 종료되기 때문에 Tomcat에서 파손된 pip 예외가 발생하지 않을 수 있습니다.이러한 차이 때문에 저도 혼란스럽습니다.
작성 중에 잘못된 HTTP 요청 URL을 사용하고 있다는 것을 알게 되었습니다.나중에 이 URL을 변경하여 문제가 해결되었습니다.업로드 URL은 http://192.168.0.31:http://192.168.0.31:http://192.168.0.31:http:/http:/http:/http:/http:/http:/http:/http:/http:serSocket Exception:부러진 파이프?예외.
그것이 저의 이유였습니다.이 문제가 발생했을 때 한 가지 더 확인하실 수 있습니다.
public void postRequest() {
Security.insertProviderAt(Conscrypt.newProvider(), 1);
System.out.println("mediafilename-->>" + mediaFileName);
String[] dirarray = mediaFileName.split("/");
String file_name = dirarray[6];
//Thread.sleep(10000);
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file",file_name, RequestBody.create(MediaType.parse("video/mp4"), new File(mediaFileName))).build();
OkHttpClient okHttpClient = new OkHttpClient();
// ExecutorService executor = newFixedThreadPool(20);
// Request request = new Request.Builder().post(requestBody).url("https://192.168.0.31:5000/uploader").build();
Request request = new Request.Builder().url("http://192.168.0.31:5000/uploader").post(requestBody).build();
// Request request = new Request.Builder().url("http://192.168.0.31:5000").build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
//
call.cancel();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),"Something went wrong:" + " ", Toast.LENGTH_SHORT).show();
}
});
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
});
System.out.println("Response ; " + response.body().toString());
// Toast.makeText(getApplicationContext(), response.body().toString(),Toast.LENGTH_LONG).show();
System.out.println(response);
}
});
Java Doc:
착신 접속 표시(접속 요구)의 최대 큐 길이는 50으로 설정되어 있습니다.큐가 꽉 찼을 때 연결 표시가 나타나면 연결이 거부됩니다.
예를 들어 ServerSocket의 "backlog" 파라미터를 늘려야 합니다.
int backlogSize = 50 ;
new ServerSocket(port, backlogSize);
언급URL : https://stackoverflow.com/questions/2309561/how-to-fix-java-net-socketexception-broken-pipe
'source' 카테고리의 다른 글
Jest: 객체 키와 값을 테스트하는 방법 (0) | 2023.01.09 |
---|---|
배열에서 쿼리 문자열을 빌드하는 PHP 함수 (0) | 2023.01.09 |
날짜/시간 열에 기반한 마지막 N일 데이터 선택 (0) | 2023.01.09 |
MySQL에서 마리아DB의 순서가 잘못되었지만 수정되었습니다. (0) | 2023.01.09 |
이중 인코딩 UTF8 문자 수정 방법(utf-8 테이블) (0) | 2023.01.09 |