2014-11-24 150 views
1

我的代码如下。当收到请求时,服务器将创建两个线程(生产者 - 消费者模式):多线程TCP服务器:java.net.SocketException:套接字关闭

... 
while(true) { 
    Socket clientSocket = server.accept(); 
    System.out.println("Got connection!"); 

    Thread consumerThread = new Thread(new ConsumerThread(sharedQueue, clientSocket)); 
    Thread producerThread = new Thread(new ProducerThread(sharedQueue, clientSocket)); 

    consumerThread.start(); 
    producerThread.start(); 
} 
... 

消费者线程读取哪些客户端发送和生产者线程返回响应。消费者:

@Override 
    public void run() { 
     try { 
      while (true) { 
       in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
       // read, do actions 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       in.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

    } 

监制:

@Override 
    public void run() { 
     try { 
      out = new PrintStream(clientSocket.getOutputStream(), true); 
      // some actions 
      out.println("something"); 

     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       out.close(); 
       clientSocket.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

但在服务器我得到以下错误:

java.net.SocketException: Socket closed 
    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.read(SocketInputStream.java:150) 
    at java.net.SocketInputStream.read(SocketInputStream.java:121) 
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) 
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) 
    at java.io.InputStreamReader.read(InputStreamReader.java:184) 
    at java.io.BufferedReader.fill(BufferedReader.java:161) 
    at java.io.BufferedReader.readLine(BufferedReader.java:324) 
    at java.io.BufferedReader.readLine(BufferedReader.java:389) 
    at ee.ut.ds.server.ConsumerThread.run(ConsumerThread.java:30) 
    at java.lang.Thread.run(Thread.java:745) 

什么可能会导致这样?我甚至看到客户端正确接受消息。另外,在生产者线程中,我关闭一个套接字。我不明白。

+0

我认为你应该在1个线程中使用输入和输出流来完成你的工作,以便正确关闭套接字。如果要并行处理输入和输出:在处理输入/输出的线程中启动新线程,并在完成所有工作时使用适当的同步关闭套接字。 – pomkine 2014-11-24 09:26:37

回答

5

您关闭套接字,并继续使用它。

不要关闭套接字,或者它的输出流,直到您已经阅读流的末尾从BufferedReader.

构建BufferedReader外循环。

您可能不需要每个套接字两个线程。

+0

在循环外部构造'BufferedReader'并没有帮助。我仍然收到同样的错误。 – Bob 2014-11-24 09:15:04

+0

您关闭了插座并继续使用它。 =>我在关闭它后使用它? – Bob 2014-11-24 09:15:49

+0

您需要做的不仅仅是我在这里推荐的三件事中的一件。尝试阅读完整的答案。您在抛出异常的地方关闭后使用套接字。这就是它被抛出的原因。这当然很明显? – EJP 2014-11-24 09:16:38

-1

您正在并行启动两个线程。你无法预测线程的细节。对于两个线程使用相同的套接字,并且如果生产者线程启动,则在finally节中关闭套接字。 你不应该关闭连接,并确保不会发生竞态条件。

+1

你能建议我应该如何修改我的代码? – Bob 2014-11-24 09:04:02

+0

准确。一个非常模糊的答案。所有线程并行运行。这就是为什么他们是线程。 – EJP 2014-11-24 09:18:39

+0

您正在关闭套接字并仍在尝试使用它.. – Shriram 2014-11-24 10:09:57

-1

问题是因为您在写入内容之后关闭了您的产品的套接字。 如果您希望套接字打开,只需关闭Producer中finally块中的输出流即可。 一旦确定没有更多的网络I/O通过套接字发生,就可以从服务器/生产者/使用者关闭套接字。

https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#close()

+0

是的,当制作人发送消息给客户端时,我不期待该客户端和服务器之间的任何通信。所以我想关闭这个套接字。我终于阻止了它。但是,如果我删除了关闭套接字的那一行,那么我仍然会得到相同的错误。 – Bob 2014-11-24 09:03:46

+0

关闭输出流将关闭套接字。和它的输入流。 – EJP 2014-11-24 09:06:26

+0

这是预期的。因为当你的线程(生产者/消费者)结束时,套接字关闭。尝试在生产者和消费者的无限循环内使用prod/consume逻辑。类似的,while(true){Producer/Consumer operations}。然后关闭服务器的套接字 – 2014-11-24 09:09:03

相关问题