【发布时间】:2018-02-11 15:02:13
【问题描述】:
我正在尝试构建一个 android 应用程序,用户可以在其中创建一个新帐户并让该帐户创建由服务器执行,并将信息添加到数据库中。
在服务器完成(或未能完成)这个任务后,我想要一个响应发送回客户端,指示任务成功或失败;我正在从我的异步任务类成员的同一个套接字打开一个inputstream 和一个outputstream。
似乎代码在从客户端发送到服务器时执行良好,并且服务器正确接收了所有内容。但是当客户端收到服务器返回的响应时,我遇到了一个错误:
09-02 15:58:02.266 30979-32154/com.example.zemcd.messagebottle E/NewAccountTask: error connecting
java.net.SocketException: recvfrom failed: EBADF (Bad file descriptor)
at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:588)
at libcore.io.IoBridge.recvfrom(IoBridge.java:552)
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:481)
at java.net.PlainSocketImpl.-wrap0(PlainSocketImpl.java)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
at libcore.io.Streams.readSingleByte(Streams.java:41)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:233)
at com.example.zemcd.messagebottle.NewAccountTask.doInBackground(NewAccountTask.java:50)
at com.example.zemcd.messagebottle.NewAccountTask.doInBackground(NewAccountTask.java:17)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: recvfrom failed: EBADF (Bad file descriptor)
at libcore.io.Posix.recvfromBytes(Native Method)
at libcore.io.Posix.recvfrom(Posix.java:189)
at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:250)
at libcore.io.IoBridge.recvfrom(IoBridge.java:549)
这是我的 android 客户端 asynctask 的代码,我已经指出了错误发生的位置:
public class NewAccountTask extends AsyncTask<Void, Void, Void> {
private static final String TAG = "NewAccountTask";
private static final String AUTH_KEY = "9LEF1D97001X!@:";
private static final String REQUEST_NEW_ACCOUNT = "0";
private static final int PORT = 5555;
private String mContactId;
private String mPassword;
private Context mContext;
private Socket mSocket;
private String response;
public NewAccountTask(String contactId, String password, Context context){
mContactId = contactId + ":";
mPassword = password + ":";
mContext = context;
}
@Override
protected Void doInBackground(Void... params) {
try{
mSocket = new Socket("192.168.0.111", PORT);
OutputStream out = mSocket.getOutputStream();
InputStream in = mSocket.getInputStream();
//write key to server
byte[] buffer = (AUTH_KEY + mContactId + mPassword + REQUEST_NEW_ACCOUNT).getBytes();
out.write(buffer, 0, buffer.length);
out.flush();
out.close();
//i posted a log message here this one runs
int c;
while((c = in.read()) != -1) { <--ERROR OCCURS HERE!
response += (char) c;
}
//and here this one never runs
in.close();
Log.i(TAG, "connection success!");
}catch (IOException ioe){
Log.e(TAG, "error connecting", ioe);
}
return null;
}
@Override
public void onPostExecute(Void result){
Toast.makeText(mContext, response, Toast.LENGTH_LONG).show();
}
}
这是服务器用来发送响应的方法:
public void sendResponse(byte[] response) {
OutputStream out;
try {
out = sock.getOutputStream();
out.write(response, 0, response.length);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
【问题讨论】:
-
如果读取循环永远不会退出它只能是因为对等方没有关闭连接。有没有抛出异常?
-
@EJP 没有。它不会抛出异常。它永远不会退出。
-
叹息。 peer 是否抛出异常,而不是关闭连接?
-
@EJP 没有。对等方不抛出异常。它只是停止。服务器开始接收,但似乎从未读取或写入任何数据。
-
所以 server 有一个类似的读取循环,直到 client 关闭连接才会终止。这不是一个可行的方法。例如,您需要发送和阅读行。
标签: java android sockets inputstream