我正在使用apache commons http客户端使用post方法调用url来发布参数,并且很少抛出以下错误。
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)
有人可以建议导致此异常的原因以及如何调试它吗?
答案 0 :(得分:73)
这是由:
引起的因此,在这两种情况下,您都有一个定义不明确或实施的应用程序协议。
还有第三个原因,我不会在这里记录,但是其中涉及对等方采取故意行动来重置而不是正确关闭连接。
答案 1 :(得分:28)
在我们的案例中,我们在应用服务器上执行负载测试时遇到了这种情况。问题是我们需要为JVM添加额外的内存,因为它已经用完了。这解决了这个问题。
尝试增加JVM可用的内存,或者在出现这些错误时监视内存使用情况。
答案 2 :(得分:7)
SocketException:管道损坏是由“另一端”(客户端或服务器)在代码读取或写入连接时关闭连接引起的。
这是客户端/服务器应用程序中非常常见的例外,它接收来自应用程序控件之外的客户端或服务器的流量。例如,客户端是浏览器。如果浏览器进行Ajax调用,和/或用户只是关闭页面或浏览器,那么这可以有效地杀死所有通信。基本上,只要另一端终止其应用程序,您就会看到此错误,而您并没有预料到它。
如果您在应用程序中遇到此异常,那么这意味着您应检查发生IO(输入/输出)的代码,并使用try / catch块将其包装以捕获此IOException。然后,由您决定如何处理这种半有效的情况。
在您的情况下,您仍然可以控制的最早的地方是对HttpMethodDirector.executeWithRetry
的调用 - 因此请确保使用try / catch块包装调用,并按照您认为合适的方式处理它。
我强烈建议不要在调试/跟踪级别以外的任何地方记录SocketException-Broken Pipe特定错误。否则,这可以通过填充日志作为DOS(拒绝服务)攻击的一种形式。针对这种常见情况,尝试并强化并对您的应用程序进行负面测试。
答案 3 :(得分:4)
所有开放流和&连接需要正确关闭,所以下次我们尝试使用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.
答案 4 :(得分:2)
在开发一个侦听特定TCP的简单Java应用程序时,我遇到了同样的问题。通常,我没有问题,但是当我进行一些压力测试时,我发现某些连接因错误socket write exception
而中断。
调查后,我找到了解决我的问题的解决方案。我知道这个问题已经很久了,但是我更愿意分享我的解决方案,有人会发现它很有用。
问题出在ServerSocket创建上。我从Javadoc中读取,默认限制为50个待处理的套接字。如果您尝试打开另一个连接,这些将被拒绝。解决方案仅在于在服务器端更改此默认配置。在以下情况下,我创建了一个侦听TCP端口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();
来自ServerSocket的Javadoc:
用于传入连接指示(连接请求)的最大队列长度设置为backlog参数。如果在队列已满时出现连接指示,则拒绝连接。
答案 5 :(得分:1)
我已经通过FTP服务器实现了数据下载功能,并且在恢复下载时也发现了相同的异常。 要解决此异常,您将始终必须断开与上一个会话的连接,并创建客户端的新实例以及与服务器的新连接。这种方法对HTTPClient也有帮助。
答案 6 :(得分:0)
问题可能是您使用正确的RMI方法更新了部署的文件。检查您的RMI接口是否已更新参数,或客户端没有的更新数据结构。或者您的RMI客户端没有与服务器版本不同的参数。
这只是一个有根据的猜测。在重新部署我的服务器应用程序的类文件并重新测试之后,“Broken pipe”的问题就消失了。
答案 7 :(得分:0)
以上答案说明了java.net.SocketException: Broken pipe
的原因:另一端关闭了连接。我想分享一下遇到它时发生的事情:
Content-Type
标题被错误地设置为大于请求正文实际上(事实上根本没有正文)Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
java.net.SocketTimeoutException: null
java.net.SocketException: Broken pipe
因为客户关闭了它。有时候,tomcat不会抛出破坏的pip异常,因为超时异常关闭连接,为什么这样的差异也让我感到困惑。
答案 8 :(得分:0)
我注意到我在制作它时使用了不正确的 HTTP 请求 url,后来我改变了它解决了我的问题。我的上传网址是:http://192.168.0.31:5000/uploader,而我正在使用 http://192.168.0.31:5000。那是一个 get 电话。并得到一个 java.net.SocketException: Broken pipe?例外。
这就是我的理由。这个问题可能会让你多检查一点
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);
}
});
答案 9 :(得分:-1)
的JavaDoc:
传入连接指示的最大队列长度(a 请求连接)设置为50.如果连接指示到达 当队列已满时,连接被拒绝。
你应该增加"积压" ServerSocket的参数,例如
int backlogSize = 50 ;
new ServerSocket(port, backlogSize);