我刚开始与Java Socket Programming,我已经阅读的文献插座 在这里,.以下代码是一样从一个教科书我已经采取了哪些问我找到了这一错误。比较用的文献虽然我没有看到任何错误。建立插座,bufferedreader,并printwriter似乎正确的,而他们周围都是在尝试追赶块。这是正确的"close()"ed在一试-抓住块。是否存在错误的时候通过这些进程()?任何帮助,将不胜感激。

import java.net.*;
import java.io.*;

class main{

public void process(PrintWriter out, BufferedReader in, Socket echoSocket){
//....
}

public void processData() {
    Socket echoSocket;
    PrintWriter out;
    BufferedReader in;
    try{
        echoSocket = new Socket("server.company.com", 8081);
        out = new PrintWriter(echoSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
    }
    catch (Exception e) {
        System.err.println("Exception has occured");
        return;
    }
    process(out, in, echoSocket);
    try {
        out.close();
        in.close();
        echoSocket.close();
    }
    catch(IOException e) {
        System.err.println("IOException has occurred.");
    }
  }
}
有帮助吗?

解决方案

虽然,打字错误尽管如此,人们只能猜测是什么实际的"错误",这种代码中有一个问题,与错误的处理。具体地说,在处置的资源。

讨论有关的资源

什么资源?

基本上:Java的任何对象,依靠基础的操作系统级别的资源。主要是:IO资源(输入和输出流,频道)、插座。但更重要的是:如果"的事情"你是用了一个 close, dispsose, shutdown 或任何一样,它当然保留对资源的内部。
有一些例外情况(值得注意的是 ByteArrayInputStream 有没有资源而存储器),但是这些都是执行情况的详细信息:如果你坚持他们的接口(和你应该,这是一个"合同"),每一个流应该被关闭。
由于Java7,大多数的这些对象的API实施 AutoCloseable 接口,但许多第3次缔约方不一定移植到这他们的代码(也许有些不能为其他原因)。

作为一个代码审查人员在我的公司:我停止阅读和我拒绝任何代码,只要我没有看到一个安全的呼吁 close 方法的一个资源。通过安全的我的意思是内的最后条款,保证来执行的。

规则有关资源

任何 资源获得通过你的程序应该释放在一个 finally 条款(有些人甚至加:其自己的)。

什么是典型生命周期的资源 还有:

  1. 你得到它
  2. 你用它
  3. 你释放它

在你的代码,就是

ResourceObject myObject = null;
try {
    myObject = getResource();
    processResource(myObject);
} finally {
    if(myObject != null) {
        try {
            myObject.close();
        } catch (Exception e) {
            // Usually there is nothing one can do but log
        }
    }
}

由于Java7,如果资源对象实现了 AutoCloseable你有一个新的写作方式,这就是所谓的"尝试用资源"。

try(ResourceObject myObject = getResource()) {
    process(myObject);
}

你看不到最后,但它的存在,编译器写的最后条款对于你在那种情况。

什么关于多资源?

还有:多资源,多finallys.这个想法是单独的失败的原因在不同的最后条款。说你想要复制一文件...

public void myCopy() throws IOException {
InputStream source = null;
    try {
    source = new FileInputStream("yourInputFile");
        // If anything bad happens, I have a finally clause that protects this now   
        OutputStream destination = null;
    try {
        destination = new FileOutputStream("yourOurputFile"); // If fails, my Input will be closed thanks to its own finally
            performCopy(source, destination); // If this fail, my destination will also be closed thanks to its own finally
        } finally {
            if(destination!=null) { try { destination.close(); } catch (Exception e) {/* log*/ }}
        }
    } finally {
        if(source!=null) { try { source.close(); } catch (Exception e) {/* log*/ }}
    }
}

或者,Java7语法,我们在较短(免责声明:我没有Java7现在,所以不可能真正地检查,如果这个编译):

try(
    InputStream input = new FileInputStream("in");
    OutputStream output = new FileOutputStream("out")) {
    performCopy(input, output);
} catch(IOException e) {
    // You still have to deal with it of course.
}

这是如此的多样板!

是的,它是。这就是为什么我们有图书馆。一个可以争辩说你不应写入这样的代码。使用标准,表现良好像图书馆知识共享IO,或使用他们的一个实用的方法。或新JAVA方法喜欢的 Files API,并看看如何运作的。

Commons IO有一个方便 IOUtils.closeQuietly() 套方法,用于封闭流。

尝试用的资源陷阱

有影响的"试用资源"的呼吁,一位深得多。这些包括:如果我想做些什么的例外情况发生在最后条款?我怎么区分,从一个例外,将已经发生过 performCopy?另一种情况是:这里发生了什么:

try(Reader reader = new InputStreamReader(new FileInputStream("in"), "an encoding that is not supported")) {
  // Whatever
}

它发生, UnsupportedEncodingException 是扔但是 FileInputStream 是instanciated.但作为 FileInputStream 不是问题的尝试条款,它将不被关闭。一个你有一个文件描述泄漏。尝试一千次,你JVM将不能公开的文件了,你OS会告诉你"最大数目的开放的文件超过了"(ulimit 一般不会在UNIX)

回到你的座

所以你们有什么资源?

嗯,首先,我们可以注意到只有一个真正的资源,您的座的实例,因为插座如果是的话,为什么不试说,(如果是的话,为什么不试):

 * <p> Closing this socket will also close the socket's
 * {@link java.io.InputStream InputStream} and
 * {@link java.io.OutputStream OutputStream}.

所以你的输入和输出流绑到你的座,这是不够的。

什么是错你的代码

添加意见的一种原始代码:

try{
    echoSocket = new Socket("server.company.com", 8081);
    out = new PrintWriter(echoSocket.getOutputStream(), true); // This can throw IOException
    in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream())); // Ditto
}
catch (Exception e) {
    // If an exception was thrown getting any of the streams, we get there
    System.err.println("Exception has occured");
    // And you return without closing the socket. It's bad !
    return;
}
// Let's assume everything worked, no exception.
process(out, in, echoSocket); // This may throw an exception (timeout, socket closed by peer, ...) 
                              // that is uncaught (no catch clause). Your socket will be left unclosed as a result.
try {
    out.close();              // This can fail
    in.close();               // This too
    echoSocket.close();       // And this too - although nothing you can do about it
}
catch(IOException e) {
    // if out.close fails, we get here, and in.close and socket.close 
    // never got a chance to be called. You may be leaking resources 
    System.err.println("IOException has occurred.");
}

安全执行情况

Socket echoSocket = null;
try {
    // open socket, 
    echoSocket = new Socket("server.company.com", 8081); // protected by finally
    out = new PrintWriter(echoSocket.getOutputStream(), true); // protected
    in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream())); // protected
     process(out, in, echoSocket); // Still protected
} catch (Exception e) {
    // Your current error handling
} finally {
    // Anyway, this close will be called if needs be.
    if(echoSocket != null) { 
        try { echoSocket.close(); } catch (Exception e) { /* log */}
        // See javadoc, this has closed the in & out streams too.
    }
}

其他提示

public void process(){PrintWriter out, BufferedReader in, Socket echoSocket){
.

应该是

public void process(PrintWriter out, BufferedReader in, Socket echoSocket){
.

否则一切似乎对我来说似乎是良好的

试试我认为你错过了一个分号

public void processData() {
Socket echoSocket;
PrintWriter out;
BufferedReader in;
try{
    echoSocket = new Socket("localhost", 8080);
    out = new PrintWriter(echoSocket.getOutputStream(), true);
    in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
}
catch (IOException e) {
    System.err.println("Exception has occured");
    return;
}
process(out, in, echoSocket);
try {
    out.close();
    in.close();
    echoSocket.close();
}
catch(IOException e) {
    System.err.println("IOException has occurred.");
}


}
public void process (PrintWriter out,  BufferedReader in, Socket echoSocket)
{

}
.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top