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

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

创build套接字:

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

检索input和输出stream并写入一些初始数据:

 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而不是直接stream – 没有效果。

Solutions Collecting From Web of "无法读取Jelly Bean上的套接字InputStream"

我之前也看到过这个错误,虽然这个答案可能看起来不太正确,所以给它一个机会,让我知道它是否工作,出于某种原因,套接字在豆形软糖上有奇怪的行为,即使它们在较低的Android版本中工作得很好,我解决这个问题的方式是将targetSdkVersion移动到果冻bean以及项目的Android属性下的Project Build Target,并没有修改一行代码,只是出于某种原因它执行了这个操作。 。

希望这可以帮助。

问候!

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

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

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

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

我有一个类似的问题,并解决了这样的解决方法

 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适用于所有版本,并且通过任何通信协议发送和接收任何您想要的东西(甚至是JSONstring)都非常方便。 尝试像下面这样启动后台线程时将它们保存为成员variables:

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

对于asynchronous通信,后台线程可能如下所示:

 @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(<message to be ); if (mOutput == null) { // the above thread was interrupted while writing } else if (!mOutput.checkError()) { // everything went fine } else { // handle the exception } } } 

此外,你将不得不closures从外面的stream,以确保readLine不会永远阻止:

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

现在,由于您使用TCP套接字,可能会发生套接字实际上已经死了,readLine仍然阻塞。 你必须检测并closures像上面的stream。 为此,您将不得不添加另一个线程(哦),定期发送保持活动消息。 如果在X秒内没有收到来自远程设备的消息,则必须closuresstream。

整个方法确保套接字closures,所有线程在任何情况下完成。 当然,你可以使通信同步,如果这是你所需要的,通过删除发送者线程,而不是在读取器线程内包含println()。 我希望能帮到你(尽pipe答案迟了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