在 Android Studio 中使用套接字的异常
Posted
技术标签:
【中文标题】在 Android Studio 中使用套接字的异常【英文标题】:Exception Using Sockets in Android Studio 【发布时间】:2016-04-09 10:53:19 【问题描述】:我刚刚启动我的第一个 android 应用程序,但在 Android Studio 中使用套接字时遇到问题。
我正在尝试建立与服务器的连接。我正在使用异步任务执行此操作。当我启动应用程序时,创建了套接字并发送第一个包工作正常。但是当我尝试发送另一个包时,它会抛出一个异常,说套接字已关闭。
我尝试了很多事情,例如在发送第二个包之前检查套接字是否连接,如果没有,则创建一个新包。 Android Studio 中的调试告诉我,套接字“nsocket”永远不会关闭。这是我调试代码的截图:Debugging-Screenshot
这是我的异步任务代码:
public class NetworkTask extends AsyncTask<Void, byte[], Boolean>
private boolean finished = false;
private boolean socket = false;
private boolean messageSuccess = false;
Socket nsocket; //Network Socket
InputStream nis; //Network Input Stream
OutputStream nos; //Network Output Stream
SocketAddress sockaddr;
Client c = new Client();
Context context = getApplicationContext();
@Override
protected void onPreExecute()
Log.i("AsyncTask", "onPreExecute");
@Override
protected Boolean doInBackground(Void... params) //This runs on a different thread
socket = false;
try
Log.i("AsyncTask", "doInBackground: Creating socket");
sockaddr = new InetSocketAddress(SERVERHOST, SERVERPORT);
nsocket = new Socket();
nsocket.connect(sockaddr, 10000); //10 second connection timeout
socket = true;
while (finished)
finished = false;
if (nsocket.isConnected())
Log.i("AsyncTask", "doInBackground: Socket created, streams assigned");
Log.i("AsyncTask", "doInBackground: Waiting for inital data...");
else
catch (IOException e)
e.printStackTrace();
Log.i("AsyncTask", "doInBackground: IOException");
socket = false;
catch (Exception e)
e.printStackTrace();
Log.i("AsyncTask", "doInBackground: Exception");
socket = false;
return socket;
public boolean closeSocket()
try
//nis.close();
nos.close();
nsocket.close();
Log.i("AsyncTask", "closeSocket: Finished");
socket = false;
return true;
catch (IOException e)
Log.i("AsyncTask", "closeSocket: IO Failed");
e.printStackTrace();
return false;
catch (NullPointerException e)
Log.i("AsyncTask", "closeSocket: Socket or output Stream already closed.");
e.printStackTrace();
socket = false;
return false;
catch (Exception e)
Log.i("AsyncTask", "closeSocket: Failed");
e.printStackTrace();
return false;
public boolean SendDataToNetwork(final String cmd) //You run this from the main thread.
if (!nsocket.isClosed())
Log.i("AsyncTask", getString(R.string.StatusSendAlarm));
Log.i("AsyncTask", cmd);
messageSuccess = false;
publishProgress("1".getBytes());
try
new Thread(new Runnable()
public void run()
try
nos = nsocket.getOutputStream();
nos.write(cmd.getBytes());
nos.flush();
nos.close();
finished = true;
messageSuccess = true;
catch (Exception e)
e.printStackTrace();
Log.i(TAG, "SendDataToNetwork: Message send failed. Caught an exception");
publishProgress("2".getBytes());
).start();
catch (Exception e)
Log.i("AsyncTask", "SendDataToNetwork: Message send failed. Caught an exception");
publishProgress("3".getBytes());
Log.i("AsyncTask", "SendDataToNetwork: Message send failed. Socket closed");
return messageSuccess;
@Override
protected void onProgressUpdate(byte[]... values)
if (values.length > 0)
if (values[0].equals("1"))
Log.i("AsyncTask", "onProgressUpdate: " + values[0].length + " bytes received.");
c.toastmessage(context, getString(R.string.StatusSendAlarm), Toast.LENGTH_SHORT);
else if (values[0].equals("2"))
Log.i("AsyncTask", "onProgressUpdate2: " + values[0].length + " bytes received.");
c.toastmessage(context, getString(R.string.StatusSendAlarmFail)+" 2", Toast.LENGTH_SHORT);
else if (values[0].equals("3"))
Log.i("AsyncTask", "onProgressUpdate3: " + values[0].length + " bytes received.");
c.toastmessage(context, getString(R.string.StatusSendAlarmFail)+" 3", Toast.LENGTH_SHORT);
//textStatus.setText(new String(values[0]));
@Override
protected void onCancelled()
Log.i("AsyncTask", "Cancelled.");
@Override
protected void onPostExecute(Boolean result)
if (socket)
Log.d("AsyncTask", getString(R.string.socket_success));
if (nos != null)
if (messageSuccess)
c.toastmessage(context, getString(R.string.alarm_success),Toast.LENGTH_LONG);
mCheckBox.toggle();
else
c.toastmessage(context, getString(R.string.alarm_fail),Toast.LENGTH_LONG);
mCheckBox.toggle();
else
Log.d("AsyncTask", getString(R.string.socket_fail));
任何想法为什么会这样?
编辑:这是他的代码,其中调用了“SendDataToNetwork”函数:
private OnClickListener btnSendListener = new OnClickListener()
public void onClick(View v)
//toastmessage(context, "Sending Message to AsyncTask.", Toast.LENGTH_LONG);
EditText at = (EditText) findViewById(R.id.alarmText);
Long tsLong = System.currentTimeMillis()/1000;
String ts = tsLong.toString();
String atext = at.getText().toString();
if (atext.length() > 0)
String alarmtext = "<event>\n" +
"<address>" + EINHEIT + "</address>\n" +
"<timestamp>" + ts + "</timestamp>\n" +
"<message>" + atext + "</message>\n" +
"</event>";
networktask.SendDataToNetwork(alarmtext);
;
这是我的 onCreate 函数,用于建立套接字连接。
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnSend = (Button)findViewById(R.id.sendButton);
btnSend.setOnClickListener(btnSendListener);
mButton=(Button)findViewById( R.id.sendButton);
mCheckBox= ( CheckBox ) findViewById( R.id.checkBox_send);
mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
if (isChecked)
mButton.setEnabled(true);
mButton.setTextColor(Color.parseColor("#ffffff"));
else
mButton.setEnabled(false);
mButton.setTextColor(Color.parseColor("#7c0000"));
);
context = getApplicationContext();
networktask = new NetworkTask(); //New instance of NetworkTask
networktask.execute();
【问题讨论】:
可能服务器收到第一条消息后关闭了连接。 'public boolean SendDataToNetwork(final String cmd) //你从主线程运行这个。'。确实。因此,从您的 AsyncTask 类中删除此函数并将其放入您的活动中。然后显示你第一次和第二次调用它的时间和方式。 当我按下 UI 上的按钮时,该函数被调用。我添加了上面的代码 你为什么不评论我的第一条评论? Repeat: '从你的 AsyncTask 类中移除这个函数,然后把它放到你的活动中'。 【参考方案1】: nos.close();
您自己正在关闭流并因此关闭套接字。
nos = nsocket.getOutputStream();
你应该只做一次。不是每条消息。
【讨论】:
不幸的是,当我没有关闭输出流时,它没有发送消息。 我按照你一开始说的方式得到了它,在想知道为什么它没有发送消息之后,我关闭了输出流并且它起作用了。 好的。当发送者的nos.write(cmd.getBytes());
与接收者的read()
不匹配时,经常会发生这种情况。接收者试图读取什么?一些字节?一条线?我认为你没有发送一条线。
我要发送的文本是 "nos.write((cmd + "\n").getBytes());
或nos.write((cmd + "\n\n").getBytes());
你必须找出接收者期望的消息结束。询问制作接收器的人。你没有回答我的问题接收者试图阅读什么。【参考方案2】:
我找到了解决问题的方法。我采纳了您的建议(连接、发送、阅读一项任务)并实施了它。现在调用了异步任务,当我按下按钮并将字符串传递给 doInBackground 函数时。我在那里创建套接字连接,打开 OutputStream 并发送消息。之后我关闭所有连接。
我不得不继续使用“nos.close()”,因为发送“\n”或“\n\n”不起作用。
异步任务调用
private OnClickListener btnSendListener = new OnClickListener()
public void onClick(View v)
EditText at = (EditText) findViewById(R.id.alarmText);
Long tsLong = System.currentTimeMillis()/1000;
String ts = tsLong.toString();
String atext = at.getText().toString();
if (atext.length() > 0)
String alarmtext =
"<event>\n" +
"<address>" + EINHEIT + "</address>\n" +
"<timestamp>" + ts + "</timestamp>\n" +
"<message>" + atext + "</message>\n" +
"</event>";
networktask = new NetworkTask(); //New instance of NetworkTask
networktask.execute(alarmtext);
else
toastmessage(context, getString(R.string.noText), Toast.LENGTH_LONG);
;
创建套接字
protected Boolean doInBackground(String... params) //This runs on a different thread
messageSuccess = false;
String alarmtext = params[0];
try
Log.i("AsyncTask", "Background Task: Creating socket...");
sockaddr = new InetSocketAddress(SERVERHOST, SERVERPORT);
nsocket = new Socket();
nsocket.connect(sockaddr, 10000); //10 second connection timeout
Log.i("AsyncTask", "Background Task: Socket created");
nos = nsocket.getOutputStream();
nos.write(alarmtext.getBytes());
closeSocket();
messageSuccess = true;
catch (IOException e)
e.printStackTrace();
Log.e("AsyncTask", "Background Task: IOException");
Log.i("AsyncTask", getString(R.string.socket_fail));
messageSuccess = false;
catch (Exception e)
e.printStackTrace();
Log.e("AsyncTask", "Background Task: Exception");
Log.i("AsyncTask", getString(R.string.socket_fail));
messageSuccess = false;
return messageSuccess;
感谢 greenapps 的帮助
【讨论】:
一些备注:如果你只在 doInBackground 中使用 messageSuccess、sockaddr 和 nsocket(我认为你这样做),然后在那里声明它们。进一步使用 e.getMessage() 来查看正确的消息。 Log.e("AsyncTask", "后台任务:IOException:" + e.getMessage());以上是关于在 Android Studio 中使用套接字的异常的主要内容,如果未能解决你的问题,请参考以下文章
在 Unity 中使用 Android Studio 上的类
无法使用 java 套接字将图像从 android studio 发送到 pc,filePath 返回 null
在Android Studio中关闭手机上的应用程序时如何不关闭套接字