2013-07-25 29 views
1

我試圖使用NIO服務器來讀/寫TCP連接的客戶端。我建立了一個成功的連接,並且我的初始消息被髮送到服務器並被正確處理。它表示服務器正在發回消息,但我沒有收到客戶端的任何輸入。此外,在服務器發回消息後,應用程序崩潰,說它試圖讀取空指針(第127行服務器代碼)。Android NIO服務器選擇器在沒有消息發送的情況下正在讀取

重要的是要指出,我是這個概念的新手,並且我不太瞭解選擇器。我看過教程,但矛盾的消息讓我對這個問題更加困惑。如果任何人有關於這個主題的任何好的教程,我會非常感激。

這是我的代碼。

客戶主要活動屏幕

package com.example.client; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.TextView; 

import com.example.client.ServerService.Connect; 



public class MainActivity extends Activity { 

    Button button; 
    TextView textView; 
    EditText editText; 
    EditText editTextps; 
    static Handler handler; 
    Connect connect=null; 
    Object myLock=new Object(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     button=(Button) findViewById(R.id.button1); 
     textView=(TextView) findViewById(R.id.textView1); 
     editText=(EditText) findViewById(R.id.editText1); 
     editTextps=(EditText) findViewById(R.id.editText2); 
     handler=new Handler(){ 
      @Override 
      public void handleMessage(Message msg) { //Handle code for receiving messages 
       super.handleMessage(msg);//when a message is received it's input is processed here 
       Bundle bundle=msg.getData(); 
       if(bundle.getInt("int") == 2){ 
        if(bundle.getInt("valid") == 1){ 
         Intent i = new Intent(); 
         i.setClassName("com.example.client", 
           "com.example.client.ReadyScreen"); 
         startActivity(i); 
        }else{ 
         alertMessage(); 
         editText.setText(""); 
         editTextps.setText(""); 
        } 
       } 
      } 

     }; 

     startService(new Intent(getBaseContext(), ServerService.class)); 


     button.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View arg0) { 
       String str=editText.getText().toString(); 
       String strps=editTextps.getText().toString(); 
       Message msg=Message.obtain(); 
       Bundle bundle=new Bundle(); 
       bundle.putString("name", str); 
       bundle.putString("password", strps); 
       msg.setData(bundle); 
       ServerService.threadHandler.sendMessage(msg); 
      } 
     }); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    public void alertMessage() { 

     final android.app.AlertDialog.Builder show = new AlertDialog.Builder(this).setTitle("Error").setMessage("Wrong username/password").setNeutralButton("close", null); 
     show.show(); 
    } 
} 

在那裏我運行的連接和IO服務器服務

package com.example.client; 

import java.net.InetSocketAddress; 
import java.net.SocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.SocketChannel; 

import android.app.Service; 
import android.content.Intent; 
import android.os.Handler; 
import android.os.IBinder; 
import android.os.Looper; 
import android.os.Message; 
import android.util.Log; 
import android.widget.Toast; 

public class ServerService extends Service { 

    Handler handler; 
    static MyHandle threadHandler; 
    Connect connect=null; 
    Object myLock=new Object(); 
    static SocketChannel socketChannel=null; 
    public ByteBuffer sendBuffer=ByteBuffer.allocate(1024); 
    static ByteBuffer receiveBuffer=ByteBuffer.allocate(1024); 
    static Selector selector; 
    private static final String TAG = ServerService.class.getSimpleName(); 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId){ 
     Log.d(TAG, "Started running the service"); 
     System.out.println(TAG + "Started running the service"); 

     (new Thread(new ReceivingThread())).start(); 
     (new Thread(new SendingThread())).start(); 

     return START_STICKY; 
    } 


    @Override 
    public void onDestroy(){ 
     super.onDestroy(); 
     Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show(); 
    } 

    class Connect { 
     SocketChannel socketChannel=null; 
     public ByteBuffer sendBuffer=ByteBuffer.allocate(1024); 
     ByteBuffer receiveBuffer=ByteBuffer.allocate(1024); 
     Selector selector; 
     public Connect() { 

      try { 
       socketChannel=SocketChannel.open(); 
       SocketAddress remoteAddress=new InetSocketAddress("192.168.2.17", 20001); 
       socketChannel.connect(remoteAddress); 
       socketChannel.configureBlocking(false); 
       selector=Selector.open(); 
       socketChannel.register(selector, SelectionKey.OP_READ); 
      } catch (Exception e) { 

       e.printStackTrace(); 
      } 
     } 
    } 

    public class ReceivingThread implements Runnable{ 

     @Override 
     public void run() { 
      Log.d(TAG, "Started running the receive thread"); 
      connect=new Connect(); 
      try { 
       while(true){ 
        if(connect.selector.select()==0) 
         continue; 
        Play receivedMessage = new Play(); 
        receivedMessage.play(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
       System.out.println(e.getMessage()); 
      } 
     } 

    } 

    public class SendingThread implements Runnable{ 

     @Override 
     public void run() { 
      Log.d(TAG, "Started running the send thread"); 
      Looper.prepare(); 
      threadHandler=new MyHandle(Looper.myLooper()); 
      Looper.loop(); 
     } 

    } 

    class MyHandle extends Handler{ 
     public MyHandle(){ 
     } 
     public MyHandle(Looper looper){ 
        super(looper); 
     } 
     public void handleMessage(Message msg){ 
      String str=msg.getData().getString("name"); 
      String strps=msg.getData().getString("password"); 
      MyMessage message=new MyMessage(); 
      message.setb((byte)1); 
      message.setUsername(str); 
      message.setPassword(strps); 
      try { 
       connect.sendBuffer.clear(); 
       connect.sendBuffer.put(message.Message2Byte()); 
       connect.sendBuffer.flip(); 
       connect.socketChannel.write(connect.sendBuffer); 
      } catch (Exception e) { 

       e.printStackTrace(); 
      } 
     } 
    } 

} 

服務器代碼

package mytcp; 

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.ServerSocketChannel; 
import java.nio.channels.SocketChannel; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
import java.util.Set; 
import java.util.Timer; 
import java.util.TimerTask; 

public class NioServer { 

    /** 
    * @param args 
    */ 
    private int port = 20001; 
    final makeFlagFalse timerFlag = new makeFlagFalse(); 
    static makeFlagFalse loginLoopBoolean = new makeFlagFalse(); 
    private static ByteBuffer sBuffer = ByteBuffer.allocate(1024); 
    private static ByteBuffer rBuffer = ByteBuffer.allocate(1024); 
    private static Map<SocketChannel, Integer> clientsMap = new HashMap<SocketChannel, Integer>(); 
    private Selector selector = null; 
    private ServerSocketChannel serverSocketChannel = null; 
    private Object gate = new Object(); 

    public NioServer(int port) { 
     this.port = port; 
     try { 
      init(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) throws InterruptedException, IOException { 
     final NioServer server = new NioServer(20001); 
     Thread accept = new Thread() { 
      public void run() { 
       server.accept(); 
      } 
     }; 

     accept.start(); 
     while (loginLoopBoolean.flag == true) 
      server.loginService(); 
     server.gamePlay(clientsMap); 
    } 

    public void init() throws IOException { 
     selector = Selector.open(); 
     serverSocketChannel = ServerSocketChannel.open(); 
     serverSocketChannel.socket().setReuseAddress(true); 
     // serverSocketChannel.configureBlocking(false); 
     serverSocketChannel.socket().bind(new InetSocketAddress(port)); 
     System.out.println("服務器啓動"); 
    } 

    public void accept() { 
     while (true) { 
      try { 
       SocketChannel socketChannel = serverSocketChannel.accept(); 
       System.out.println("receive the connection from " 
         + socketChannel.socket().getInetAddress() + ":" 
         + socketChannel.socket().getPort()); 

       socketChannel.configureBlocking(false); 
       synchronized (gate) { 
        selector.wakeup(); 
        socketChannel.register(selector, SelectionKey.OP_READ); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
       System.out.println(e.getMessage()); 
       System.out.println("Damn it"); 
      } 
     } 
    } 

    public void loginService() throws InterruptedException { 


      synchronized (gate) { 
      } 
      try { 
       int n = selector.select(); 
       if (n == 0){} 
       else{ 
       Set<SelectionKey> selectionKeys = selector.selectedKeys(); 
       for (SelectionKey key : selectionKeys) { 
        try { 
         if (key.isReadable()) { 
          handle_receive_login(key); 
         } 
        } catch (Exception e) { 
         try { 
          if (key != null) { 
           key.cancel(); 
           key.channel().close(); 
          } 
         } catch (Exception ex) { 
          e.printStackTrace(); 
         } 
        } 
       } 
       selectionKeys.clear(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

    } 

    public void handle_receive_login(SelectionKey key) { 
     SocketChannel socketChannel = null; 
     ServerMessage message = null; 
     ServerMessage sendMessage = new ServerMessage(); 
     socketChannel = (SocketChannel) key.channel(); 
     rBuffer.clear(); 
     try { 
      int count = socketChannel.read(rBuffer); 
      if (count > 0) { 
       rBuffer.flip(); 
       message = ServerMessage.byte2Message(rBuffer.array()); 
       System.out.println("Receive from"+ socketChannel.socket().getInetAddress() + " : "+ message.getb()); 
       switch(message.getb()){ 
       case(1): 
         int valid = DB.idCheck(message.getUsername(), 
           message.getPassword()); 
         sendMessage.setb((byte) 2); 
         sendMessage.setValid(valid); 
         sendMes sendMes = new sendMes(sendMessage, socketChannel); 
         sendMes.send(); 

        break; 
       case(2): 
        break; 
       case (3): 
        if(timerFlag.flag){ 
         if(message.getReady() == 1){ 
          if(clientsMap.size() < 6){ 
           clientsMap.put(socketChannel, clientsMap.size() + 1); 
           sendMessage.setb((byte) 3); 
           sendMessage.setReady(1); 
           sendMes sendMes1 = new sendMes(sendMessage, socketChannel); 
           sendMes1.send(); 
          } 

          else{ 
           sendMessage.setb((byte) 3); 
           sendMessage.setReady(0); 
           sendMes sendMes1 = new sendMes(sendMessage, socketChannel); 
           sendMes1.send(); 
          } 

          Timer timer = new Timer(); 

          System.out.println("flag is " + timerFlag.flag); 
          TimerTask task = new TimerTask(){ 
           public void run(){ 
            timerFlag.falsify(); 
            System.out.println("flag now is " + timerFlag.flag); 
           } 
          }; 
          timer.schedule(task, 20*1000); 
         } 
        }else{ 
         sendMessage.setb((byte) -1); /*-1 implies that game is currently in progress*/ 
         sendMes sendMes1 = new sendMes(sendMessage, socketChannel); 
         sendMes1.send(); 
        } 
        break; 

       case (4): 
        if(timerFlag.flag == true){ 
         sendMessage.setb((byte) -2); /*send message saying "waiting for other players*/ 
         sendMes sendMes1 = new sendMes(sendMessage, socketChannel); 
         sendMes1.send(); 
        }else{ 
         loginLoopBoolean.falsify(); 
        } 
        break; 
       } 
      }/*end of if(count=0)*/ 
     } catch (Exception e) { 
      e.printStackTrace(); 
      key.cancel(); 
      try { 
       socketChannel.close(); 
      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 
     } 

    } 


    public void gamePlay(Map<SocketChannel, Integer> clientsMap) throws IOException, InterruptedException{ 
     Dealer dealer = new Dealer(); 
     dealer.createDeck(); 
     ServerMessage sendMessage = new ServerMessage(); 

     if(!clientsMap.isEmpty()){ 
      Set<SocketChannel> clientSet = clientsMap.keySet(); 
      Iterator<SocketChannel> iterator=clientSet.iterator(); 
      SocketChannel currentPlayer; 
      while(iterator.hasNext()){ 
       currentPlayer=iterator.next(); 
       sendMessage.setb((byte) 4); 
       sendMessage.setCard1(dealer.dealCard(dealer.deck)); 
       sendMessage.setCard2(dealer.dealCard(dealer.deck)); 
       sendMes sendMes1 = new sendMes(sendMessage, currentPlayer); 
       sendMes1.send(); 
      } 
      //send who's turn it is 
      loginService(); 
     } 
    } 

    public static class makeFlagFalse{ 
     boolean flag; 
     public makeFlagFalse() { 
      this.flag = true; 
     } 
     public void falsify(){ 
      flag = false; 
     } 
     public void makeTrue(){ 
      flag = true; 
     } 
    } 

    public class sendMes{ 
     ServerMessage message; 
     SocketChannel currentPlayer; 

     sendMes(ServerMessage message,SocketChannel currentPlayer){ 
      this.message = message; 
      this.currentPlayer=currentPlayer; 
     } 
     public void send() throws IOException{ 
      sBuffer.clear(); 
      sBuffer.put(message.Message2Byte()); 
      sBuffer.flip(); 
      currentPlayer.write(sBuffer); 
     } 
    } 


} 

我欣賞任何形式的的幫助。

謝謝

+0

你真的希望能夠理清自己的空指針異常,但是這是第127行? – EJP

+0

int count = socketChannel.read(rBuffer);在服務器代碼中 – BCza

回答

0
private Object gate = new Object(); 

應該是揮發性

相關問題