2013-03-27 108 views
4

到目前爲止,我能夠在一個Android設備(wifi tethering/hotspot)上啓動服務器,並讓客戶端(另一個android)連接並將消息發送到服務器。服務器然後回覆。我意識到我需要一種方法來讓服務器監聽客戶端,即使聊天應用程序沒有運行。客戶端應該能夠發送消息,並且服務器應該收到這個消息。 我應該使用Service還是IntentService來實現這個?我不能從AsyncTask &服務擴展...如何實現這個?一些示例代碼會很棒。使用服務或IntentService的Android客戶端/服務器套接字通信

這是我的服務器看起來像:

public class Server extends AsyncTask<Integer, Void, Socket> { 

    private ServerSocket serverSocket; 
    private TextView textView; 
    private String incomingMsg; 
    private String outgoingMsg; 

    public Server(TextView textView) { 
     this.textView = textView; 
    } 

    public void closeServer() { 
     try { 
      serverSocket.close(); 
     } catch (IOException e) { 
      Log.d("Server", "Closung the server caused a problem"); 
      e.printStackTrace(); 
     }  
    } 


    @Override 
    protected Socket doInBackground(Integer... params) { 

     try { 
      serverSocket = new ServerSocket(params[0]);  

      //accept connections 
      Socket socket = serverSocket.accept(); 

      BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 
      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

      incomingMsg = in.readLine() + System.getProperty("line.separator"); 

      //send a message 
      outgoingMsg = "You are connected to the Server" + System.getProperty("line.separator"); 
      out.write(outgoingMsg); 
      out.flush(); 

      return socket; 


     } catch (InterruptedIOException e) { 
      //if timeout occurs 
      e.printStackTrace(); 

     } catch (IOException e) { 
      e.printStackTrace(); 

     } 
//  finally { 
//   if (serverSocket != null) { 
//    try { 
//     serverSocket.close(); 
//    } catch (IOException e) { 
//     e.printStackTrace(); 
//    } 
//   } 
//  } 

     return null; 
    } 


    protected void onPostExecute(Socket socket) { 

     if(socket != null) { 
      try { 

       Log.i("Server", "Server received: " + incomingMsg); 
       textView.setText("Server received: " + incomingMsg + "\n"); 

       textView.append("Server sent: " + outgoingMsg + "\n"); 
       Log.i("Server", "Server sent: " + outgoingMsg); 

       socket.close(); 

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

     } else { 
      Log.d("Server", "Can't communicate with the client!"); 
     } 
    } 
} 

這是我的客戶:

public class Client extends AsyncTask<Integer, Void, Socket> { 

    private WifiManager wifi; 
    private Context context; 
    private String outMsg; 
    private String inMsg; 

    public Client(Context context, WifiManager wifiManager) { 
     this.context = context; 
     this.wifi = wifiManager; 
    } 

    @Override 
    protected Socket doInBackground(Integer... params) { 

     try { 

      String gateway = intToIp(wifi.getDhcpInfo().gateway); 
      Socket socket = new Socket(gateway, params[0]); 

      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 

      String ipAdress = intToIp(wifi.getConnectionInfo().getIpAddress()); 

      outMsg = ", Client " + ipAdress +" is connecting!" + System.getProperty("line.separator"); 
      out.write(outMsg); 
      out.flush(); 

      //accept server response 
      inMsg = in.readLine() + System.getProperty("line.separator"); 

      return socket; 

     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 


    public String intToIp(int addr) { 
     return ((addr & 0xFF) + "." + 
       ((addr >>>= 8) & 0xFF) + "." + 
       ((addr >>>= 8) & 0xFF) + "." + 
       ((addr >>>= 8) & 0xFF)); 
    } 


    protected void onPostExecute(Socket socket) { 

     if(socket != null) { 

      Log.i("Client", "Client sent: " + outMsg); 
      Toast.makeText(context, "\nClient sent: " + outMsg + "\n", Toast.LENGTH_LONG).show(); 

      Log.i("Client", "Client received: " + inMsg); 
      Toast.makeText(context, "Client received: " + inMsg + "\n", Toast.LENGTH_LONG).show(); 

     } else { 
      Log.d("Client", "Can't connect to server!"); 
      Toast.makeText(context, "Can't connect to server!", Toast.LENGTH_LONG).show(); 
     }   
    } 
} 

如何使服務從服務器中?客戶是否也應該服務?

+0

沒有剛在服務 – 2013-03-27 15:34:37

+0

ok了服務器,怎麼樣使用服務或IntentService?在服務的情況下如何將這與AsyncTask結合? – user574080 2013-03-27 16:10:01

回答

3

使用服務,但忘記了AsyncTask。讓你的服務啓動你的通用線程(https://developer.android.com/reference/java/lang/Thread.html)並設置你的套接字+監聽器。該服務甚至可以處理消息的發送(通過以下鏈接中涵蓋的衆多選項之一)。

不要忘記正確地清理服務的onDestroy()中的線程。

另請注意,如果您希望應用程序繼續接收來自其他客戶端的消息,則需要確保該服務被強制置於前臺(請參閱http://developer.android.com/reference/android/app/Service.html#startForeground(int,android.app.Notification)。但是,這並非萬無一失,您的服務仍然可能會被殺死。

這就是爲什麼人們傾向於使用一些專用的盒子託管,而不是各個設備的服務器...

+0

會在這裏謹慎使用帶有newFixedThreadPool的ExecutorService(http://developer.android.com/reference/java/util/concurrent/Executors.html#newFixedThreadPool)嗎? – 2013-12-17 20:17:38

+0

當然,如果您運行多個線程,最好使用ExecutorService來管理它們。一個新的FixedThreadPool可能意味着你限制了可以連接的用戶數量,這取決於你如何構建服務器(什麼協議等)。 – kwazi 2014-05-07 00:36:57