2015-10-28 49 views
1

我正在做一个奇怪的问题做java套接字项目。这里是我的代码: 服务器:java套接字地址已经在使用异常

package second.sockets; 

import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.ArrayList; 
import java.util.List; 

public class Server implements Runnable { 

    public static String HOST = "localhost"; 
    public static int PORT = 1234; 

    private static final int MAX_USERS = 2; 
    private static final Server serverInstance = new Server(); 
    private ServerSocket serverSocket; 
    private List<User> users = new ArrayList<>(); 

    private Server() { 
     try { 
      if(this.serverSocket == null) { 
       this.serverSocket = new ServerSocket(Server.PORT); 
      } 
     } catch(IOException e) { 
      e.printStackTrace(); 
      System.err.println("could not initialize ServerSocket on port="+Server.PORT + 
        "["+ e.getMessage() +"]"); 
     } 
    } 

    public static Server getInstance() { 
     return Server.serverInstance; 
    } 

    @Override 
    public void run() { 
     System.out.println("waiting for incoming connections..."); 
     try { 
      while(!Thread.interrupted()) { 
       this.waitForFreeSlots(); 
       Socket newSocket=null; 
       try { 
        newSocket = this.serverSocket.accept(); 
        System.out.println("new connection " + newSocket); 
       } catch(IOException e) { 
        System.err.println("could not connect"); 
       } 
      } 
     } catch(InterruptedException e) { 
      System.err.println("server interrupted"); 
     } 
    } 

    private synchronized void waitForFreeSlots() throws InterruptedException { 
     while(this.users.size() >= Server.MAX_USERS) { 
      this.wait(); 
     } 
    } 

    public static int getPORT() { 
     return PORT; 
    } 

    public static void main(String[] args) { 

     Server server = Server.getInstance(); 
     Thread serverThread = new Thread(server); 
     serverThread.start(); 

    } 
} 

客户:

package second.sockets; 

import java.io.IOException; 
import java.net.Socket; 
import java.net.UnknownHostException; 

public class Client { 

    public static void main(String[] args) { 
     Socket socket=null; 
     try { 
      socket = new Socket(Server.HOST, Server.PORT); 
     } catch(UnknownHostException uhe) { 
      System.err.println("could not connect to "+Server.HOST+" on port "+Server.PORT+", no such host"); 
     } catch(IOException ioe) { 
      System.err.println("could not connect to "+Server.HOST + " on port "+Server.PORT); 
     } 
     System.out.println(socket); 
    } 

} 

我运行服务器和它的作品,但是当我运行一个客户端,我得到could not initialize ServerSocket on port=1234[Address already in use: JVM_Bind],它是从服务器代码行25。这很奇怪,因为Server是一个单身人士,所以没有多于一个班级的实例。客户main功能甚至没有触及它。我不明白,问题出在哪里?谢谢。编辑: 这是堆栈跟踪。它来自Server的构造函数,虽然它是私有的,并且在运行客户端之后显示。

java.net.BindException: Address already in use: JVM_Bind 
    at java.net.DualStackPlainSocketImpl.bind0(Native Method) 
    at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106) 
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382) 
    at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190) 
    at java.net.ServerSocket.bind(ServerSocket.java:375) 
    at java.net.ServerSocket.<init>(ServerSocket.java:237) 
    at java.net.ServerSocket.<init>(ServerSocket.java:128) 
    at second.sockets.Server.<init>(Server.java:22) 
    at second.sockets.Server.<clinit>(Server.java:15) 
    at second.sockets.Client.main(Client.java:12) 
    could not initialize ServerSocket on port=21234[Address already in use: JVM_Bind] 
    Socket[addr=localhost/127.0.0.1,port=21234,localport=53054] 

我没有得到这个过渡: at second.sockets.Client.main(Client.java:12) - >at second.sockets.Server.<clinit>(Server.java:15)

+0

1234上还有其他东西在运行吗? – Makoto

+0

该端口似乎并不重要,因为我尝试使用'Server.PORT'的一些随机值。行为每次都是一样的。 – kcdsh

+0

那些低于1024的“随机值”?这些端口需要特殊许可才能使用。尝试一个这样的数字,就像21234;任何应用程序使用的可能性都很小。 – Makoto

回答

0

您在例外看到的东西来自于事实,你在你的客户端代码中使用Server.HOST和Server.PORT 。这将调用Server类的类初始化程序。在这个初始化器中,创建了Server类中的所有静态内容。我看到你有一个静态的服务器实例在那里......所以你实际上已经创建了几个服务器实例。

因此,请避免在客户端代码中使用Server.HOST和Server.PORT,并直接使用真正的valus,它将起作用。

正常情况下,当您想要在两个代码实体之间共享内容时,将它们移动到第三个实体以分离服务器和客户端。然后让服务器和客户端使用该新实体。

+0

基本上我在单例方法中出错了。如果引用为null,它应该在方法'getInstance()'中进行初始化。 – kcdsh

+0

问题是客户端代码不应该影响服务器代码的结构。因此,对于服务器,您仍然可以采用单例方法(无论这是否是一个好主意是另一回事)。只要确保你有第三个类,例如包含常量HOST和PORT的ServerSettings。 – mattiash

0

好的,我找出了错在哪里。在这一行客户端socket = new Socket(Server.HOST, Server.PORT);我使用了Server类中的2个变量。当我删除它并粘贴原始值或将变量加入为final时,它开始工作。这是一些疯狂的魔法。

+0

没有野性魔法。阅读我的答案。 – mattiash

相关问题