无法在Jelly Bean上读取套接字InputStream

我有一个TCP套接字连接,在Android 2.3上运行良好但现在面临Android 4.1上的一些问题。 问题是InputStream.read()方法总是返回-1(没有阻塞),就像关闭连接一样。

创建套接字:

SocketFactory socketFactory = SocketFactory.getDefault(); Socket socket = socketFactory.createSocket("c.whatsapp.net", 5222); socket.setSoTimeout(3*60*1000); socket.setTcpNoDelay(true); 

检索输入和输出流并编写一些初始数据:

 InputStream inputStream = new BufferedInputStream(socket.getInputStream()); OutputStream outputStream = new BufferedOutputStream(socket.getOutputStream()); outputStream.write(87); outputStream.write(65); outputStream.write(1); outputStream.write(2); outputStream.flush(); 

然后,这个条件总是不受阻塞地通过:

 int c = inputStream.read(); if (c < 0) { Log.d(TAG, "End of stream"); } 

此代码在后台线程中运行 。 它正在研究姜饼。

试图使用InputStreamReader和OutputStreamWriter而不是直接流 – 没有效果。

我以前看过同样的错误,虽然这个答案可能看起来像offtopic给它一个机会让我知道它是否有效,由于某种原因,套接字在jellybean上有奇怪的行为,即使它们在较低的android版本中工作完全正常,我解决这个问题的方法是将targetSdkVersion移动到果冻豆以及项目的Android属性下的Project Build Target,没有修改一行代码,只是这样,并且由于某种原因它可以解决问题。 。

希望这可以帮助。

问候!

我有一些类似的问题,其中inputStream.read()返回-1,我没有得到任何exception。 事实上,服务器已关闭,连接断开。 我没有使用不同的版本测试它,只有4.0。

以下是有关此行为的Google Bug报告 。

不幸的是,这个bug的状态似乎是“封闭的”,因为它不可重现。

我的工作是将-1解释为套接字的关闭和无法访问的服务器。 当您尝试重新连接时,您会收到正确的错误。

我遇到了类似的问题并通过这样的解决方法修复了它

 private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); private static class WatchDog implements Runnable{ private Thread thread = Thread.currentThread(); public void run() { Log.d(LOG_TAG, "Interrupting read due to timeout"); thread.interrupt(); } } private void read(InputStream in, ByteBuffer bb, long waitTime) throws IOException { int startingPos = bb.position(); long timeout = System.currentTimeMillis() + RESPONSE_TIMEOUT; ScheduledFuture watchdogFuture = executor.schedule(new WatchDog(), RESPONSE_TIMEOUT, TimeUnit.MILLISECONDS); try { while(System.currentTimeMillis() < timeout && bb.hasRemaining()){ //workaround fixing timeout after 1ms try{ int read = in.read(bb.array(), bb.position(), bb.remaining()); if(read > 0){ bb.position(bb.position()+read); } } catch(SocketTimeoutException e){} if(bb.hasRemaining()){ Thread.sleep(5); } } watchdogFuture.cancel(true); } catch (InterruptedException e) {} if(bb.hasRemaining()){ throw new SocketTimeoutException("Unable to read requested bytes: " + (bb.position()-startingPos) + "/" + (bb.limit()-startingPos) + " after " + (System.currentTimeMillis() - timeout + RESPONSE_TIMEOUT) + "ms"); } } 

使用BufferedReader和PrintWriter可以为我的所有版本工作,非常方便通过任何通信协议发送和接收任何你想要的东西(甚至是JSON字符串)。 尝试在启动后台线程时将它们保存为成员variables,如下所示:

 mInput = new BufferedReader(new InputStreamReader( socket.getInputStream())); mOutput = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true); 

对于异步通信,您的后台线程可能如下所示:

 @Override public final void run() { while (!Thread.currentThread().isInterrupted()) { if (mInput == null) { break; } String message = null; try { message = mInput.readLine(); } catch (IOException e) { // handle the exception as you like break; } if (Thread.currentThread().isInterrupted()) { // thread was interrupted while reading break; } else if (message != null) { // handle the message as you like } } } 

使用另一个后台线程发送消息:

 @Override public void run() { if (mOutput != null) { mOutput.println( 

此外,您必须从外部关闭流以确保readLine不会永久阻止:

 try { mOutput.close(); mInput.close(); mOutput = null; mInput = null; } catch (IOException e) { // log the exception } 

现在,由于您正在使用TCP套接字,因此套接字实际上可能已经死亡并且readLine仍然处于阻塞状态。 你必须像上面那样检测到并关闭流。 为此,您将不得不添加另一个周期性发送keep-alive-messages的线程(哦)。 如果在X秒内没有从远程设备收到消息,则必须关闭流。

这整个方法确保套接字关闭,所有线程在所有情况下都完成。 当然,通过删除sender-thread并在reader-thread中包含println(),您可以使通信同步,如果这是您所需要的。 我希望能帮助你(即使答案是8个月后)。

朋友,

尝试inputStream.readLine(); (即) DataInputStream.readLine(); (弃用方法)

这对我有用……

试试这个代码 –

 Runnable runnable = new Runnable() { @Override public void run() { synchronized (this) { Socket s = null; String inMsg = null, msg2 = null; try { try { s = new Socket(server, port); } catch (Exception e) { return; } BufferedReader in = new BufferedReader( new InputStreamReader(s.getInputStream())); BufferedWriter out = new BufferedWriter( new OutputStreamWriter(s.getOutputStream())); try { inMsg = in.readLine() + System.getProperty("line.separator"); } catch (Exception e) { return; } out.write(message + "\n\r"); out.flush(); try { msg2 = in.readLine(); if (msg2 == null) { return; } } catch (Exception e) { return; } out.close(); s.close(); } catch (Exception e) { return; } } } }; 

这个对我有用。

你应该使用Apache Commons IO: http : //commons.apache.org/proper/commons-io/

请参阅IOUtils.copy() http://commons.apache.org/proper/commons-io/javadocs/api-release/index.html?org/apache/commons/io/package-summary.html