使用Service或IntentService进行Android Client / Server Socket通信

时间:2013-03-27 15:30:37

标签: android sockets android-service

到目前为止,我能够在一个Android设备(wifi tethering / hotspot)上启动服务器,并让客户端(另一个android)连接并向服务器发送消息。然后服务器回复了那个。我意识到我需要一种方法来保持服​​务器监听客户端,即使聊天应用程序没有运行。客户端应该能够发送消息,服务器应该收到此消息。 我应该使用Service或IntentService来实现这个目标吗?我无法从AsyncTask&服务......如何实现这个?一些示例代码会很棒。

这就是我的服务器的样子:

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();
        }           
    }
}

如何从服务器中取出服务?客户也应该是服务吗?

1 个答案:

答案 0 :(得分: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)。但是,这不是万无一失的,你的服务仍然可以被杀死。

这就是为什么人们倾向于使用托管在某个专用盒子上的服务器而不是每个单独的设备......