简体   繁体   English

Android套接字输入流读取(后跟EPIPE)

[英]Android socket inputstream read (followed by an EPIPE)

I am creating some client-side socket software to read events from a server. 我正在创建一些客户端套接字软件来从服务器读取事件。 (For example, streaming stock quotes). (例如,流媒体股票报价)。

PROBLEM: .read(b); 问题: .read(b); is returning immediately with a value of -1 . 立即返回值为-1 This causes an infinte loop and the phone becomes very hot. 这导致infinte循环,手机变得非常热。 Additionally, all checks to s.isConnected(), isOpen(), isBound() return true. 此外,对s.isConnected(),isOpen(),isBound()的所有检查都返回true。 Essentially the socket looks connected . 套接字本质上是连接的 (This is an error scenario, so any value of .setSoTimeout(x) has no effect. 12 minutes, or leave empty. The .read(b) always returns -1 immediately). (这是一个错误场景,因此.setSoTimeout(x)的任何值都没有效果.12分钟,或留空.read(b)总是立即返回-1)。

When I write to it later, via the getOutputStream(), I receive an exception EPIPE (broken pipe). 当我稍后写入它时,通过getOutputStream(),我收到一个异常EPIPE(断开的管道)。

Here's the core code (log statements/value checks omitted for brevity). 这是核心代码(为简洁起见,省略了日志语句/值检查)。

s.connect(new InetSocketAddress(host, port), CONNECT_TIMEOUT_MILLIS);

byte[] b = new byte[1024];
while (s.isConnected()) {
    int bytesToRead = s.getInputStream().read(b);
    if (bytesToRead <= 0) {
        LOGGER.debug("no bytes read? trying again.");
        continue;
    }
    processFrame(b);
}

If I cycle the 3g on the phone, it works fine. 如果我在手机上循环3g,它可以正常工作。 Sometimes it gets into this weird state. 有时它会进入这种奇怪的状态。

Question

Am I doing something wrong? 难道我做错了什么? Is this the expected behavior? 这是预期的行为吗? Is there existing code I could look at to show the right way to do socket programming on Android? 是否有我可以看到的现有代码来展示在Android上进行套接字编程的正确方法?

If read(byte[], ...) returns < 0, the peer has closed the connection, so you must close the socket and exit the loop. 如果read(byte[], ...)返回<0,则对等体已关闭连接,因此您必须关闭套接字并退出循环。 There will never be any more data. 永远不会有更多的数据。

Input streams are blocking, so the only way read(byte[], ...) can return zero is if you specify a zero length buffer or a zero length, depending on which overload you call. 输入流是阻塞的,因此read(byte[], ...)的唯一方法是返回零,如果指定零长度缓冲区或零长度,则取决于您调用的过载。 As you aren't doing that, it will never return zero. 正如你没有这样做,它永远不会返回零。

Instead it will do exactly what it says in the Javadoc: either return -1 meaning EOS, or block until at least one byte of data is available. 相反,它将完全按照它在Javadoc中所说的内容执行:返回-1表示EOS,或阻塞直到至少有一个字节的数据可用。

Am I doing something wrong? 难道我做错了什么?

Almost everything. 几乎所有的。 Your loop testing for <= 0 is completely pointless and completely incorrect. 您对<= 0循环测试完全没有意义且完全不正确。 And so is testing isConnected() . 测试isConnected()也是如此。 That only tells you whether you ever connected this Socket . 这只会告诉你是否连接过这个Socket It doesn't change with the state of the connection. 它不会随着连接状态而改变。 The return code of -1 tells you that. 返回代码-1告诉你。 Your loop should read: 你的循环应该是:

while ((bytesToRead = s.getInputStream().read(b)) > 0)
{
    // do something with b[0..bytesToRead -1].
}
s.close();

I use the following code without problem: 我没有问题使用以下代码:

        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = null;
        while ((line = in.readLine()) != null) {
            myLineProcess(line); //here you process you line result
        }

good luck. 祝好运。

Well i don't know whether this would be the appropriate answer for this, but still i will like to give you the code, which does works well every time. 嗯,我不知道这是否适合这个,但我仍然想给你代码,每次都很好。

Please keep it simple, 请保持简单,

Try using InputStream, InputStreamReader, BufferedReader, OutputStream, PrintWriter. 尝试使用InputStream, InputStreamReader, BufferedReader, OutputStream, PrintWriter.

Client Side: 客户端:

Socket s = new Socket();
s.connect(new InetSocketAddress("Server_IP",Port_no),TimeOut); 
// Let Timeout be 5000

Server Side: 服务器端:

ServerSocket ss = new ServerSocket(Port_no);
Socket incoming = ss.accept();

For Reading from the Socket: 从套接字读取:

InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);

BufferedReader br = new BufferedReader(isr);
boolean isDone = false;

String s = new String();

while(!isDone && ((s=br.readLine())!=null)){

     System.out.println(s);   // Printing on Console

 }

For Writing to the Socket: 写入套接字:

OutputStream os = s.getOuptStream();
PrintWriter pw = new PrintWriter(os)

pw.println("Hello");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM