我正在尝试在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");
}
答案 0 :(得分:0)
我能够通过在while循环中的ListenAsyncTask中创建BufferedReader来解决问题。