2012-09-21 82 views
1

我已經找到了一個解決方案,但是我找不到一個解決方案。我試圖編寫一個套接字鎖,所以我的程序一次只能運行一個實例,但我得到一個套接字關閉異常。這裏是我的SocketCode代碼在accept()調用上拋出的套接字異常正在拋出

package utilities; 

import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.SocketAddress; 

import utilities.enums.ClientType; 

public class SocketLocker { 
    private final int PORT; 
    private ServerSocket serverSocket; 
    private Socket clientSocket; 

    public SocketLocker(ClientType cType) { 
     serverSocket = null; 
     clientSocket = null; 
     switch (cType) 
      { 
      case PRODUCER: 
       PORT = 7856; 
       break; 
      case CONSUMER: 
       PORT = 7857; 
       break; 
      default: 
       PORT = 7859; 
      } 
    } 

    public boolean getLock() { 
     try { 
      serverSocket = new ServerSocket(PORT,1); 
      clientSocket = serverSocket.accept(); 
      return true; 
     } catch (IOException e) { 
      // TODO: log event 
      e.printStackTrace(); 
     } 
     return false; 
    } 

    public void releaseLock() { 
     try { 
      if (clientSocket != null) 
       clientSocket.close(); 
      if (serverSocket != null) 
       serverSocket.close(); 
     } catch (IOException e) { 
      // TODO: Log event 

     } 
    } 
} 

這是我的單元測試代碼這就是我正在得到異常:

package utilities; 

import static org.junit.Assert.assertFalse; 
import static org.junit.Assert.assertTrue; 

import org.junit.After; 
import org.junit.Before; 
import org.junit.Test; 

import utilities.enums.ClientType; 

public class SocketLockerTest { 

    private SocketLocker producerLocker; 
    private SocketLocker consumerLocker; 

    @Before 
    public void start() { 
     producerLocker = new SocketLocker(ClientType.PRODUCER); 
     consumerLocker = new SocketLocker(ClientType.CONSUMER); 
    } 

    @Test(timeout = 10000) 
    public void lockProducer() { 
     assertTrue(producerLocker.getLock()); 
    } 

    @Test(timeout = 10000) 
    public void lockConsumer() { 
     assertTrue(consumerLocker.getLock()); 
    } 

    @Test(timeout = 10000) 
    public void lockProducerTwice() { 
     producerLocker.getLock(); 
     assertFalse(producerLocker.getLock()); 
    } 

    @Test(timeout = 10000) 
    public void lockSeparately() { 
     producerLocker.getLock(); 
     assertTrue(consumerLocker.getLock()); 
    } 

    @Test(timeout = 10000) 
    public void lockProdcuerSeparateObject(){ 
     producerLocker.getLock(); 
     assertFalse(new SocketLocker(ClientType.PRODUCER).getLock()); 
    } 

    @After 
    public void finish() { 
     producerLocker.releaseLock(); 
     consumerLocker.releaseLock(); 
    } 
} 

而這裏的例外:

java.net.SocketException: socket closed 
    at java.net.PlainSocketImpl.socketAccept(Native Method) 
    at java.net.PlainSocketImpl.accept(Unknown Source) 
    at java.net.ServerSocket.implAccept(Unknown Source) 
    at java.net.ServerSocket.accept(Unknown Source) 
    at utilities.SocketLocker.getLock(SocketLocker.java:34) 
    at utilities.SocketLockerTest.lockProducer(SocketLockerTest.java:25) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.FailOnTimeout$1.run(FailOnTimeout.java:28) 

回答

0

如果服務器套接字的目的只是爲了防止一次運行兩個實例,根本沒有必要接受連接。只要刪除客戶端套接字變量和accept()調用即可。你沒有實現一個鎖,但實際上是一個死鎖。

+0

這不是很好的答案 – 2012-09-21 21:41:18

+1

@matheszabi這不是一個好答案*爲什麼?*這樣的陳述對任何人都是100%無用的。同樣,無法解釋的downvotes基本上只是網站破壞行爲。實際上,答案不僅糾正了OP引用的測試問題,而且還糾正了他的應用中的一個主要設計缺陷。如果你不明白你應該提問。你應該在傾聽的時候說話。 – EJP

+0

我猜這是一個downvote :) –

1

測試超時失敗。當你調用

@Test(timeout = 10000) 
    public void lockProducer() { 
     assertTrue(producerLocker.getLock()); 
    } 

會發生什麼它,你打開指定端口的服務器套接字,然後等待進入的連接。

serverSocket = new ServerSocket(PORT,1); 
clientSocket = serverSocket.accept(); 

因此,您的代碼將等待接受,直到超時,因爲您沒有發起連接嘗試。