2014-09-01 34 views
9

我试图使用套接字实现HTTP服务器。如果客户端(例如浏览器)请求目录,服务器将显示可用文件的列表。客户端请求文件时出现问题。我得到以下错误:java.net.SocketException:通过peer重置连接:套接字写入错误在服务文件时

java.net.SocketException: Connection reset by peer: socket write error 
at java.net.SocketOutputStream.socketWrite0(Native Method) 
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113) 
at java.net.SocketOutputStream.write(SocketOutputStream.java:159) 
at cf.charly1811.java.web.RequestHandler.writeFile(RequestHandler.java:152) 
at cf.charly1811.java.web.RequestHandler.processRequest(RequestHandler.java:139) 
at cf.charly1811.java.web.RequestHandler.handleRequest(RequestHandler.java:110) 
at cf.charly1811.java.web.RequestHandler.run(RequestHandler.java:86) 
at java.lang.Thread.run(Thread.java:745) 

堆栈跟踪显示问题从writeFile()方法来:

private void writeFile(File request) throws IOException 
{ 
    InputStream byteReader = new BufferedInputStream(new FileInputStream(request)); 
    byte[] buffer = new byte[1024]; 
    int bytesRead; 
    while ((bytesRead = byteReader.read(buffer)) != -1) 
    { 
     outputStream.write(buffer, 0, bytesRead); 
    } 
    byteReader.close(); 
} 

但我无法弄清楚什么是错的。 你能帮我吗?

编辑

谢谢大家对你的答案。在我阅读你的答案之后,我明白问题在于发生错误时的Socket。这里的是我的错误代码:

// Method to process a single request 
handleRequest() throw IOException 
{ 
    // process here 
    // if the client request a file 
    writeFile(); 
    // close socket when the request is processed 
} 

// The method is called 
public run() 
{ 
    try{ 
     // If an error occurs the try/catch won't be called because it is implemented outside the loop. So when an IOException occurs, the loop just stop and exit the program 
     while(true) 
     { 
      handleRequest(); 
     } 
    } 
    catch(IOException e) { 
     // Handle exception here 
    } 
} 

我的新的代码一直在寻找这样的:

// Method to process a single request 
handleRequest() 
{ 
    try { 
     // process here 
     // if the client request a file 
     writeFile(); 
     // close socket when the request is processed 
    } 
    // If this exception occurs the catch() method will be called 
    catch(IOException e) 
    { 
     // handle exception here 
    } 
} 

// The method is called 
public run() 
{ 
    while(true) 
     { 
      handleRequest(); 
     } 
    } 
} 
+1

您可能需要查看远程主机上发生了什么(“clent”)。建议:尝试[Wireshark](http://www.wireshark.org)。 – FoggyDay 2014-09-01 19:14:26

+0

当发生IOException时,'while(true)'循环必须正常退出。编辑中的新代码存在一个新问题,即如果套接字异常关闭,“while”循环将永远旋转。 – bond 2014-09-02 02:44:49

+0

@baconoverlord你对此有何建议? – 2014-09-02 02:47:19

回答

11

TCP套接字可能“关闭”并且您的代码尚未被通知。

这是一个生命周期的动画。 http://tcp.cs.st-andrews.ac.uk/index.shtml?page=connection_lifecycle

基本上,连接被客户端关闭。您已有throws IOExceptionSocketException延伸至IOException。这工作得很好。你只需要正确处理IOException,因为它是api的正常组成部分。

编辑:RST数据包发生在一个不存在或关闭的套接字上接收到数据包时。对您的应用程序没有任何影响。取决于实施情况,reset状态可能会持续,closed永远不会正式发生。

+0

* port *可能是'CLOSING',但该状态与此问题无关。这意味着两端同时关闭,在这种情况下,此写入会抛出“套接字关闭”异常。 – EJP 2014-09-02 00:47:38

+0

它表示'由对等重置:套接字写入错误'。当一个目的地收到一个封闭套接字的数据包时,会发生RST重置数据包。两端之一以异常方式终止连接,或者它发生得太快(可能在回送中),发生在中间关闭时。我经常看到这个错误足以知道'write()'上的所有IOExceptions应该像连接关闭一样处理。 – bond 2014-09-02 01:02:13

+0

@EJP它与这个问题有关。试图解释生命周期,而不是你对“已被同伴关闭的连接”的回答。错误本身表示“通过同级重置”。你不应该为每天使用套接字工作的人降低工作效率,并且看到在生产中的每个主要操作系统上都可以想到各种可能的中间状态。 – bond 2014-09-02 01:06:35

1

这个问题通常是通过写那些已经被同行关闭连接造成的。在这种情况下,它可能表明用户取消了下载例如。

相关问题