2013-03-27 73 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