Android插槽服务器有多个客户端..希望关闭,但没有雪茄

时间:2014-04-25 01:32:19

标签: java android multithreading sockets

我正在尝试在Android上创建一个能够处理多个客户端连接的套接字服务器。每个客户端连接都支持异步通信。我想我的实施很接近,但我遇到了问题..

服务器应用程序在ConnectionListener上启动onCreate对象。此对象是AsyncTask对象,它创建SocketServer,然后在侦听客户端连接时循环。当它获得连接时,它会启动另一个AsyncTask对象SocketConnectionManager,并继续侦听其他客户端连接。

SocketConnectionManager创建另外两个AsycTasks - 一个用于输入,ListenAsyncTask;和一个输出,MessageAsyncTask

ListenAsyncTask从客户端套接字创建BufferedReader,并在readLine()周围循环,始终从客户端套接字中寻找输入。

MessageAsyncTask等待需要推送到客户端的消息,然后将消息推送到客户端。

我正在为所有异步任务使用自定义线程执行程序,我认为这可以避免长时间运行asnyc任务的潜在问题。

一个客户端的一切都按预期工作。当两个客户端加入时,开始看起来很好看,但最终只有最近连接的客户端消息才能通过ListenAsyncTask

我很想做的事情之一是重构使用Threads代替AsnycTasks。我认为在使用executor时我不必这样做 - 使用自定义executor我似乎能够让所有任务同时运行。

如果有人有任何建议我会非常感激。代码如下。

public class ConnectionListener extends AsyncTask<String,Socket,String> {
    private static ServerSocket serverSocket;



    private Context context;
    private GameState gameState;
    int idCounter;
    private String TAG = "Connection Listener";
    private ArrayList<SocketConnectionManager> socketConnections;

    public ConnectionListener(Context context, ServerSocket serverSocket){
        super();

        this.context = context;
        this.serverSocket = serverSocket;
        idCounter = 0;
        socketConnections = new ArrayList<SocketConnectionManager>();
    }

    @Override
    protected String doInBackground(String... params) {
        String response = "";

        Log.i(TAG, "Start listening for connections");
        while (true) {
            try {
                Log.i(TAG, "Still Looking");
                Socket clientSocket = serverSocket.accept();   //accept the client connection
                Log.i(TAG, "Connection Found");
                publishProgress(new Socket[] {clientSocket});
            } catch (IOException ex) {
                System.out.println("Problem in message reading");
            } catch (Exception e){
            }
        }
    }

    @Override
    protected void onProgressUpdate(Socket... values) {
        super.onProgressUpdate(values);
        Log.i(TAG, "start socket connection");
        idCounter++;
        SocketConnectionManager socketConectionManager = new SocketConnectionManager(context,values[0],String.valueOf(idCounter));
        Log.i(TAG, "about to execute");
        socketConectionManager.executeOnExecutor(((FireTvApplication) context).threadPoolExecutor, (String[])null);
        Log.i(TAG, "executed");
        socketConnections.add(socketConectionManager);
     }
    @Override
    protected void onPostExecute(String result){
    }
}

SocketConnectionManager:

public class SocketConnectionManager extends AsyncTask<String,String,String> {

    private Context context;
    private MessageAsyncTask messageAsyncTask;
    private ListenAsyncTask listenAsyncTask;
    private String ipAddress;
    private Socket socket;
    private String id;

    public SocketConnectionManager(Context context, Socket socket, String id){
        this.context = context;
        this.socket = socket;
        this.id = id;

    }

    @Override
    protected String doInBackground(String... params) {
        Log.i("SocketConnetionManger", "start background task");

        startConnection();
        return "";
    }
    public void startConnection(){
        Log.i("SocketConnetionManger", "start connection");

        try{
            InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
            BufferedReader  bufferedReader = new BufferedReader(inputStreamReader); //get the client message
            Log.i("SocketConnetionManger", "waiting to read line");
            String response = bufferedReader.readLine();
            if(response == null){
                 Log.i("SocketConnetionManger","null line read - just ip test from client");
             }
            else{
                 Log.i("SocketConnetionManger","message read:" + response);
                 messageAsyncTask = new MessageAsyncTask(context,socket,id);
                 listenAsyncTask = new ListenAsyncTask(context,socket,id);
                 messageAsyncTask.executeOnExecutor(((FireTvApplication) context).threadPoolExecutor, (String[])null);
                 listenAsyncTask.executeOnExecutor(((FireTvApplication) context).threadPoolExecutor, (String[])null);
            }

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

}

ListenAsyncTask:

public class ListenAsyncTask extends AsyncTask<String,String,String> {
    private Socket client;
    private static InputStreamReader inputStreamReader;
    private static BufferedReader bufferedReader;
    private Context context;    
    private String id;
    private String TAG = "ListenAsyncTask";

    public ListenAsyncTask(Context context, Socket socket, String id){
        client = socket;
        this.context = context;
        this.id =id;

    }


    @Override
    protected String doInBackground(String... params) {
        String response = "";
        Log.i(TAG + id, "background task started");
        try {
            inputStreamReader = new InputStreamReader(client.getInputStream());
            bufferedReader = new BufferedReader(inputStreamReader); //get the client message
            while (true)
            {
                response = bufferedReader.readLine();
                if(response == null){
                    Log.i(TAG + id,"null line read");
                    break;
                }
                Log.i(TAG + id,"message read:" + response);
                JSONObject messageJson = new JSONObject(response);
                messageJson.put("id",id);
                publishProgress(new String[]{messageJson.toString()});
                Log.i(TAG + id, "message posted");
            }
            Log.i(TAG + id, "connection ended");
            inputStreamReader.close();
            client.close();   //closing the connection

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



        return response;
    }
    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        Log.i(TAG + id,"sending received intent -" + values[0]);
        Intent intent = new Intent("com.excelltech.tft.server.received");
        intent.putExtra("message",values[0]);
        context.sendBroadcast(intent);
    }
    @Override
    protected void onPostExecute(String result){
        Log.i(TAG + id,"ENDED");

    }


}

写入服务器的客户端代码如下所示。日志表明写入似乎正常工作,但在几次写入后,只有连接到服务器的最后一个客户端实际上已经收到服务器的消息。

        while (connectionEstablished){

            while(waitingForProcessing){

            }
            waitingForProcessing = true;
            String outputMessage = responseString;
            Log.i("MessageAsyncTask", "about to send message:" + outputMessage);
            printwriter.write(outputMessage + "\n");  //write the message to output stream
            printwriter.flush();
            Log.i("MessageAsyncTask", "message sent");
        }

1 个答案:

答案 0 :(得分:0)

我能够通过在while循环中的ListenAsyncTask中创建BufferedReader来解决问题。