[英]Maintaining a TCP Connection in an AsyncTask
我正在使用AsyncTask建立TCP連接並通過它發送/接收數據。
目前,我當前的代碼如下所示:
public class NetworkTask extends AsyncTask<Void, byte[], Boolean> {
Socket nsocket; //Network Socket
InputStream nis; //Network Input Stream
OutputStream nos; //Network Output Stream
boolean bSocketStarted = false;
byte[] buffer = new byte[4096];
@Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
@Override
protected Boolean doInBackground(Void... params) { //This runs on a different thread
boolean result = false;
try {
// Connect to address
Log.i(TAG, "doInBackground: Creating socket");
SocketAddress sockaddr = new InetSocketAddress("google.de", 80);
nsocket = new Socket();
nsocket.connect(sockaddr, 5000); //10 second connection timeout
if (nsocket.isConnected()) {
bSocketStarted = true;
nis = nsocket.getInputStream();
nos = nsocket.getOutputStream();
Log.i("AsyncTask", "doInBackground: Socket created, streams assigned");
Log.i("AsyncTask", "doInBackground: Waiting for inital data...");
int read = nis.read(buffer, 0, 4096); //This is blocking
while(bSocketStarted) {
if (read > 0){
byte[] tempdata = new byte[read];
System.arraycopy(buffer, 0, tempdata, 0, read);
publishProgress(tempdata);
Log.i(TAG, "doInBackground: Got some data");
}
}
}
} catch (IOException e) {
e.printStackTrace();
Log.i(TAG, "doInBackground: IOException");
result = true;
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "doInBackground: Exception");
result = true;
} finally {
try {
nis.close();
nos.close();
nsocket.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.i(TAG, "doInBackground: Finished");
}
return result;
}
public boolean SendDataToNetwork(final byte[] cmd) { //You run this from the main thread.
// Wait until socket is open and ready to use
waitForSocketToConnect();
if (nsocket.isConnected()) {
Log.i(TAG, "SendDataToNetwork: Writing received message to socket");
new Thread(new Runnable() {
public void run() {
try {
nos.write(cmd);
}
catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "SendDataToNetwork: Message send failed. Caught an exception");
}
}
}
).start();
return true;
}
else
Log.i(TAG, "SendDataToNetwork: Cannot send message. Socket is closed");
return false;
}
public boolean waitForSocketToConnect() {
// immediately return if socket is already open
if (bSocketStarted)
return true;
// Wait until socket is open and ready to use
int count = 0;
while (!bSocketStarted && count < 10000) {
try {
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
count += 500;
}
return bSocketStarted;
}
@Override
protected void onProgressUpdate(byte[]... values) {
try {
if (values.length > 0) {
Log.i(TAG, "onProgressUpdate: " + values[0].length + " bytes received.");
String str = new String(buffer, "UTF8");
Log.i(TAG,str);
tv.setText(str);
tv.setMovementMethod(new ScrollingMovementMethod());
}
} catch (Exception e) {
e.printStackTrace();
}
finally {}
}
@Override
protected void onCancelled() {
Log.i(TAG, "Cancelled.");
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
Log.i(TAG, "onPostExecute: Completed with an Error.");
} else {
Log.i(TAG, "onPostExecute: Completed.");
}
}
}
我可以實例化任務並從我的活動中調用SendDataToNetwork
。 但是,我傳遞給SendDataToNetwork的所有文本(例如“ GET / HTTP / 1.1”)都會連續發送到服務器。
如何修改我的代碼以維護doInBackground
的連接, doInBackground
也沒做,直到我調用SendDataToNetwork
並將字節發送到服務器后,才等到准備好發送新數據為止? 基本上,我想運行AsyncTask,直到我明確取消(=關閉連接)為止。
nsocket.connect(sockaddr, 5000); //10 second connection timeout
if (nsocket.isConnected()) {
測試毫無意義。 如果未連接套接字,則connect()
會引發異常。
您的讀取循環從根本上還是有缺陷的,因為它不會一直讀取。 有關如何讀取流的標准解決方案,例如:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
您的waitForSocketToConnect()
方法實際上也沒有做任何有用的事情。
您需要重新考慮所有這一切。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.