2012-09-21 47 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(); 

因此,您的代码将等待接受,直到超时,因为您没有发起连接尝试。