2012-04-25 288 views
2

首先,我不太确定如何解释,没有听起来令人困惑,所以我会尽量简化。我有一个服务器应用程序,可以将两个客户端“配对”,作为双人游戏的一部分。发生的方式是,当第一个客户端连接到服务器时,套接字连接被接受,则使用该客户端创建一个新的ClientProtocol线程但未启动。当另一个客户端连接到服务器时,他被添加到前一个线程中,然后启动该线程。该线程知道两个输入流和两个输出流,每个客户端一个。但是,当我尝试从客户端或服务器端读取时,没有任何反应。这适用于单个线程中的单个客户端。下面是一些代码:Java客户端服务器/一个线程多个客户端

服务器端(主线程)

public static Queue<ContestProtocol> contesters; 

public static void main(String[] args) throws IOException { 
    ServerSocket serverSocket = null; 
    contesters = new LinkedList<ContestProtocol>(); 

    try { 
     serverSocket = new ServerSocket(4444); 
    } catch (IOException e) { 
     System.err.println("Could not listen on port: 4444."); 
     System.exit(-1); 
    } 

    while (true) { 
     Socket socket = serverSocket.accept(); 

     ObjectInputStream ois; 
     ObjectOutputStream oos; 

     try { 
      ois = new ObjectInputStream(socket.getInputStream()); 
      oos = new ObjectOutputStream(socket.getOutputStream()); 

      synchronized (contesters) { 
       if (contesters.size() == 0) { 
        Contester contester1 = new contester(ois, oos); 
        contesters.add(new ContestProtocol(contester1)); 
       } else { 
        Contester contester2 = new Contester(ois, oos); 
        contesters.poll().hook(contester2).start(); 
       } 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

服务器端(ContestProtocol)

private Contester contester1, contester2; 

public ContestProtocol(Contester contester1) { 
    super("ContestProtocol"); 
} 

public ContestProtocol hook(Contester contester2) { 
    this.contester2 = contester2; 
    return this; 
} 

public void run() { 
    try { 
     contester1.getOOS().writeInt(-1); 
     contester2.getOOS().writeInt(-2); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

服务器端(contester):

public Contester(ObjectInputStream ois, ObjectOutputStream oos) { 
    this.ois = ois; 
    this.oos = oos; 
} 

public ObjectInputStream getOIS() { 
    return ois; 
} 

public ObjectOutputStream getOOS() { 
    return oos; 
} 

客户端:

try { 
      socket = new Socket(serverAddr, 4444); 
      oos = new ObjectOutputStream(socket.getOutputStream()); 
      ois = new ObjectInputStream(socket.getInputStream()); 
      int selectedChampion = ois.readInt(); 
} catch (Exception e) { 
       e.printStackTrace(); 
} 

ContestProtocol线程完成执行没有问题,但两个客户端挂在readInt()。我不懂为什么。

+0

我不确定如果我喜欢你接近这个方式,但是,但是,这两个客户端应该得到这些整数。 Wireshark说什么?数据是否从服务器中传出? – 2012-04-25 15:51:52

+0

经过一些测试后,似乎有些线程必须互相阻塞。调用ois.available()将挂起在调试器中。 – Renaud 2012-04-25 16:07:59

+0

噢,我预见了你的设计不起作用,但无聊,客户应该在服务器锁定一些阅读电话之前得到他们的意见。 – 2012-04-25 18:01:18

回答

0

访问资源时必须执行互斥或信号量问题: 您正在使用的流(在本例中为输出流和输入流)正在读取和写入相同的资源。 由于所有这些进程都在继续的一个线程上进行,因此它们的线程正在相互中断,并在另一个线程上创建等待进程。
一个解决方案是,您在流对象上注册事件标记,以便每当完成一个事件时,另一个只会启动。

+0

不存在流从线程的开始到结束。如果我关闭了一个流,我关闭了套接字。 – Renaud 2012-04-25 15:41:22

+0

我不知道我是否理解你所说的“正在读取和写入相同的资源”,据我了解,objectInputStream和ObjectOutputStream正在写入和读取到两个不同的套接字。它有效,如果我有一个客户端读取和写入到服务器。不过我可能会误解。 – Renaud 2012-04-25 16:10:14

+0

我只是忘了在这里调用flush(): public void run(){ 尝试contester1.getOOS()。writeInt(-1); (); flush(); contester2.getOOS()。writeInt(-2); (); flush(); (例外e){ e。的printStackTrace(); } } – Renaud 2012-04-25 16:20:51

0

你应该循环你的客户端双向输入流。

while(true){ 
if(ois.avaible() > 0) 
ois.readInt(); 
} 

提示:考虑异步网络与网状,以获得更好的性能。