2013-04-04 74 views
0

我试图创建一个服务器,使用多个端口,因此不同的数据和信息可以很容易地发送和接收,但在我的doInBackground方法中,我的代码卡在一个socket.receive, 这里是我的代码doInBackground卡住

while(run) 
    { 
     //GameServerID 
     try 
     { 
      if(gameServerID == null) 
      { 
       gameServerID = new DatagramSocket(portID); 
      } 
      //try to receive data 
      byte[] buf = new byte[256]; 
      DatagramPacket packet = new DatagramPacket(buf, buf.length); 
      try 
      { 
       Log.d(TAG, "Wait for something to connect"); 
       gameServerID.receive(packet); <--GETS STUCK HERE 
      } 
      catch (IOException e) 
      { 
       Log.d(TAG, "Error with receiving data"); 
       e.printStackTrace(); 
      } 
      String data = new String(buf, 0, packet.getLength()); 
      Log.d(TAG, data); 
      //Send out the ID to the client 
      byte[] bufer = new byte[256]; 
      //Send a message "connect" to the host 
      String msg = Integer.toString(players); 
      players = players + 1; 
      bufer = msg.getBytes(); 
      InetAddress address; 
      //Default ip address of the host 
      address = packet.getAddress(); 
      DatagramPacket p = new DatagramPacket(bufer, bufer.length , address, portID); 
      //Send packet 
      gameServerID.send(p); 
      addresses.add(address); 
     } 
     catch (SocketException e) 
     { 
      Log.d(TAG, "Error with socket"); 
      e.printStackTrace(); 
     } 
     //Listen for a client to connect 
     catch (IOException e) 
     { 
      Log.d(TAG, "Error with I/O"); 
      e.printStackTrace(); 
     } 

     //GameServerPositions 
     try 
     { 
      Log.d(TAG, "Run the gamePositions code"); 
      if(gamePositions == null) 
      { 
       gamePositions = new DatagramSocket(portPos); 
      } 
      //Receive position 
      //try to receive data 
      byte[] buf = new byte[256]; 
      DatagramPacket packet = new DatagramPacket(buf, buf.length); 
      try 
      { 
       gamePositions.receive(packet); 
      } 
      catch (IOException e) 
      { 
       Log.d(TAG, "Error with receiving data"); 
       e.printStackTrace(); 
      } 
      String data = new String(buf, 0, packet.getLength()); 
      Log.d(TAG, data); 
      String[] pos = data.split(":"); 
      for(int i = 0;i<pos.length;i++) 
      { 
       Log.d(TAG, pos[i]); 
      } 
      xValues[ Integer.parseInt(pos[0]) ] = Integer.parseInt(pos[1]); 
      yValues[ Integer.parseInt(pos[0]) ] = Integer.parseInt(pos[2]); 
     } 
     catch (SocketException e) 
     { 
      Log.d(TAG, "Error with socket"); 
      e.printStackTrace(); 
     } 
     //Listen for a client to connect 
     catch (IOException e) 
     { 
      Log.d(TAG, "Error with I/O"); 
      e.printStackTrace(); 
     } 

     //GameServerSendPos 
     try 
     { 
      Log.d(TAG, "Run the gamePositionsSend code"); 
      String data = ""; 
      if(gameSendPos == null) 
      { 
       gameSendPos = new DatagramSocket(portSend); 
      } 

      //create the string ready to be sent out 
      for(int i = 0; i < 8; i++) 
      { 
       if(xValues[i] >= 0) 
       { 
        data += i + ":" + xValues[i] + ":" + yValues[i] + ":"; 
       } 
      } 

      byte[] bufer = new byte[256]; 
      bufer = data.getBytes(); 
      DatagramPacket p = null; 

      for(int i = 0;i < addresses.size(); i++) 
      { 
       if(addresses.get(i) != null) 
       { 
        p = new DatagramPacket(bufer, bufer.length , addresses.get(i), portSend); 
        gameSendPos.send(p); 
       } 
      } 

     } 
     catch (SocketException e) 
     { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     catch (IOException e) 
     { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

我该怎么办才能阻止它卡住,或经过这么长时间的等待后,才跳过它?只是更多的信息,当第一个客户端连接,代码工作正常,直到它再次到达顶部,然后socket.received只是卡纸起来......

帆布

更新

我有我的代码更改为3个不同的班,我开始他们在我的服务器,同时循环,像这样

while(run) 
    { 
     if(start == true) 
     { 
      gsID.doInBackground(); 
      addresses = gsID.addresses; 
      gsPos.addresses = addresses; 
      gsPos.doInBackground(); 
      gsSendPos.addresses = addresses; 
      gsSendPos.positions = gsPos.positions; 
      gsSendPos.doInBackground(); 
      start = false; 
     } 
     else 
     { 
      addresses = gsID.addresses; 
      gsPos.addresses = addresses; 
      gsSendPos.addresses = addresses; 
      gsSendPos.positions = gsPos.positions; 
     } 
    } 

但它仍然再次被卡住的gameServerID接收方法。

我只是改变了所有的类到线程,它的效果更好,但在Android 4.0 +线程的更高版本不能从UI使用,但我不知道我是如何开始他们从不是UI?

+0

是的,正如我在答复中提到,它被“卡住”,因为'receive()'是一个阻塞的IO调用,它坐等数据可用于输入流。这段代码在你的服务器中,所以线程应该没问题。在UI方面,如果需要的话,您可以从UI线程向服务器发送数据(不熟悉Android开发)。如果你想避免在服务器上线程化并使用非阻塞IO,也检查我在NIO上的链接。换句话说, – Avi 2013-04-05 00:24:06

回答

2

从Javadoc文档DatagramSocket.receive

此方法一直阻塞数据报收到

所以你的代码是“坚持”,因为它在等待数据包到达。这意味着连接到此服务器/端口的客户端尚未发送另一个数据包,因此套接字被设计阻塞。

传统,如果你要听上在同一时间多个端口,你有两个选择:

  1. 开在不同的线程每个闭锁插座(这不会很好地扩展,如果你将有大量的客户同时由于每个线程一个客户端,但工作得很好了少量的连接)
  2. 使用NIO是非阻塞IO的Java
+0

?把所有这些分成三个不同的类,都有doInBackground方法? – Canvas 2013-04-04 10:50:01

+0

另外我将如何使用UDP NIO? – Canvas 2013-04-04 11:23:07

+0

或者您实例化3次并在3个独立线程中运行的一个类。 – Avi 2013-04-05 00:17:49