2010-01-31 4 views
-2

J'ai un problème avec une partie multijoueur. En ce moment, j'essaye juste d'obtenir que le serveur envoie le niveau courant au client. Le serveur envoie définitivement les données, mais il ne parvient jamais à l'application cliente.Problème avec Java selector/SocketChannel

Code client:

public void run() { 
    while(true) 
    { 
     try { 
      sel.select(); 
      Set readyKeys = sel.selectedKeys(); 
      Iterator itr = readyKeys.iterator(); 
      while(itr.hasNext()) 
      { 
       SelectionKey key = (SelectionKey) itr.next(); 
       itr.remove(); 
       SocketChannel ch = (SocketChannel) key.channel(); 
       if(key.isReadable()) 
       { 
        inputbuf.clear(); 
        long bytesRead = ch.read(inputbuf); 
        inputbuf.flip(); 
        byte[] test = inputbuf.array(); 
        { 
         for(int i=0; i < inputbuf.remaining(); i++) 
         { 
          System.out.print(test[i]+" "); 
         } 
        } 
        byte cmd = 0; 
        cmd = inputbuf.get(); 
        switch(cmd) 
        { 
         case 1: 
          //do something 
         case 2: 
          //do something else 
         break; 
        } 
       } 
       else if(key.isConnectable()) 
       { 
        sc.finishConnect(); 
        sc.register(sel, SelectionKey.OP_READ); 
       } 
      } 
     } catch (IOException ex) { 
      Buildsim.error("Error handling input from server", ex); 
     } 
    } 
} 

Code Serveur:

public RemotePlayer(SocketChannel s) 
{ 
    sc = s; 
    try { 
     sel = Selector.open(); 
     sc.configureBlocking(false); 
     sc.register(sel, SelectionKey.OP_WRITE); 
     socket = sc.socket(); 
     ip = socket.getInetAddress().toString(); 
     System.out.println("New connection from "+ip); 
     inputbuf = ByteBuffer.allocate(1048576); 
     outputbuf = ByteBuffer.allocate(1048576); 
     inputbuf.clear(); 
     outputbuf.clear(); 
    } 
    catch(Exception e) 
    { 
     Buildsim.error("Connection error: ", e); 
    } 
    sendLevel(); 
} 
public void sendObject(GameObject obj) 
{ 
    //Sends a packet of the object, then does the same for the object's children 
} 
public void sendLevel() 
{ 
    try { 
     outputbuf.put((byte) 0x01); 
     outputbuf.flip(); 
     sc.write(outputbuf); 
     sendObject(Buildsim.w.parts.get(0)); //root object 
    } 
    catch(IOException e) 
    { 
     Buildsim.error("Error sending level to "+ip, e); 
    } 
} 

La seule chose qui arrive au client est le 0x01 octet (signale un changement de niveau).

Merci d'avance.

+2

Dites-nous ce que vous avez fait pour essayer de l'analyser et de le déboguer. – bmargulies

+0

Avez-vous vu l'édition à ma réponse? – rsp

Répondre

0

Avec la quantité d'informations que vous nous avez donné, nous pouvons seulement donner des indications globales, comme: avez-vous vérifié que votre flux de socket n'est pas mis en mémoire tampon et que flush() après l'écriture des informations?

Les données pourraient être en attente dans un tampon en attente d'être rempli pour être envoyé.

Edit:

Vous définissez le SocketChannel en mode non-bloquant, de sorte que vous avez raison de supposer que se charge de rinçage du côté envoi, je suppose que le client ne tampon pas leur entrée?

Le problème est peut-être que SocketChannel.write() n'est pas garanti pour écrire le tampon entier, mais peut revenir tôt. Vous devez envelopper les écritures dans une boucle while pour garder trace des octets écrits pour vous assurer que vos données sont réellement écrites sur le canal. Pour citer le Javadoc:

Sauf indication contraire, une opération d'écriture retournera seulement après écrit tous les r octets demandé. Certains types de canaux, selon leur état peuvent écrire seulement certains des les octets ou éventuellement aucun. Un canal de socket en mode non bloquant, par exemple, ne peut plus écrire octets que dans le tampon de sortie du socket.

+0

Comme vous pouvez le voir dans le code, j'utilise ByteBuffers pour stocker les données. J'avais l'impression que je n'avais pas besoin de les vider, il suffit d'utiliser sc.write() pour envoyer les données dans le buffer? –