2012-02-22 7 views
0

私のプログラムのある時点でスタックしないように、ノンブロッキングソケットを読み取ろうとしています。私がいつもゼロを返そうとすると誰が知っていますか? ByteBufferには問題がありますか?この問題はlenghtが常にゼロであるreadメソッドで発生します。ノンブロッキングSocketChanelから情報を読み取る

package com.viewt.eyebird.communication; 

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.SocketChannel; 
import java.util.LinkedList; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

import com.viewt.eyebird.PhoneInformation; 
import com.viewt.eyebird.TrackingServiceData; 
import com.viewt.eyebird.commands.*; 

import android.os.Handler; 
import android.util.Log; 

final public class ServerCommunication { 

    protected final int socketTimeout; 
    protected final TrackingServiceData commandData; 
    protected final Handler handler; 
    protected final ServerCommunicationChecker clientChecker; 
    protected final LinkedList<Serialize> queue = new LinkedList<Serialize>(); 

    protected final ByteBuffer socketBuffer = ByteBuffer.allocate(1024); 
    protected final StringBuilder readBuffer = new StringBuilder(); 

    protected static final Pattern commandPattern = Pattern.compile(">[^<]+<"); 

    protected static final ServerCommand availableCommands[] = { new Panic(), 
      new ChangeServer(), new GetServer(), new Restart(), 
      new PasswordCleanup() }; 

    protected InetSocketAddress inetSocketAddress; 
    protected SocketChannel sChannel; 

    public ServerCommunication(Handler handler, String host, int port, 
      int timeAlive, int socketTimeout, 
      PhoneInformation phoneInformation, TrackingServiceData commandData) { 

     this.commandData = commandData; 
     this.handler = handler; 
     this.socketTimeout = socketTimeout; 

     try { 
      connect(host, port); 
     } catch (CommunicationException e) { 
      Log.getStackTraceString(e); 
     } 

     clientChecker = new ServerCommunicationChecker(handler, this, 
       timeAlive, new AliveResponse(phoneInformation)); 

     handler.postDelayed(clientChecker, timeAlive); 

    } 

    public void connect() throws CommunicationException { 
     try { 
      sChannel = SocketChannel.open(); 
      sChannel.configureBlocking(false); 
      sChannel.socket().setSoTimeout(socketTimeout); 
      sChannel.connect(inetSocketAddress); 
     } catch (IOException e) { 
      throw new CommunicationException(e); 
     } 
    } 

    public boolean isConnectionPending() { 
     return sChannel.isConnectionPending(); 
    } 

    public boolean finishConnection() throws CommunicationException { 
     try { 
      return sChannel.finishConnect(); 
     } catch (IOException e) { 
      throw new CommunicationException(e); 
     } 
    } 

    public void connect(String host, int port) throws CommunicationException { 
     inetSocketAddress = new InetSocketAddress(host, port); 
     connect(); 
    } 

    public void send(Serialize serialize) throws CommunicationException { 
     try { 
      sChannel.write(ByteBuffer 
        .wrap(String.valueOf(serialize).getBytes())); 
     } catch (IOException e) { 
      throw new CommunicationException(e); 
     } 
    } 

    public void sendOrQueue(Serialize serialize) { 
     try { 
      send(serialize); 
     } catch (Exception e) { 
      queue(serialize); 
     } 
    } 

    public void queue(Serialize serialize) { 
     queue.add(serialize); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     handler.removeCallbacks(clientChecker); 
     super.finalize(); 
    } 

    public void sync() throws CommunicationException { 
     int queueSize = queue.size(); 
     for (int i = 0; i < queueSize; i++) { 
      send(queue.getFirst()); 
      queue.removeFirst(); 
     } 
    } 

    public void read() throws CommunicationException { 

     int length, readed = 0; 

     try { 
      while ((length = sChannel.read(socketBuffer)) > 0) 
       for (readed = 0; readed < length; readed++) 
        readBuffer.append(socketBuffer.get()); 
     } catch (IOException e) { 
      throw new CommunicationException(e); 
     } finally { 
      socketBuffer.flip(); 
     } 

     Matcher matcher = commandPattern.matcher(readBuffer); 

     int lastCommand; 
     if ((lastCommand = readBuffer.lastIndexOf("<")) != -1) 
      readBuffer.delete(0, lastCommand); 

     while (matcher.find()) { 
      for (ServerCommand command : availableCommands) { 
       try { 
        command.command(matcher.group(), commandData); 
        break; 
       } catch (CommandBadFormatException e) { 
        continue; 
       } 
      } 
     } 

     if (length == -1) 
      throw new CommunicationException("Server closed"); 

    } 

} 

答えて

0

これは、ブロックされていないチャネルを使用しているため、データが利用可能になるまでブロックされます。利用可能なデータがない場合、ブロックせずにただちに0を返します。

+0

私はnetcatでテストしています。 $ nc -l -p 9090と入力して書き込んで送信すると、利用可能なデータに戻るはずです。 –

0

アプリケーションは常にネットワークバッファから読み取ります。

おそらく、データを送信した直後に読んでみてください.0バイトを受け取ると読み込みが停止します。あなたはネットワークにデータを返すための時間を全く与えなかった。

代わりに、ループを読み、データがない場合は、Thread.sleep(time)(約100〜300ミリ秒)で少しスリープしてから、もう一度やり直してください。

すでに長い時間待っている場合は、ループを停止する必要があります。スリープをカウントし、データを取得したらリセットします。または、すべてのデータが読み込まれると停止します。

+0

私は本当にこれを行う別の管理クラスによって定義される300msの時間を与えます。好奇心で、私がパッケージを正しく送っているかどうかを確認しました。 –

関連する問題