2012-09-25 38 views
1

我正在创建一些客户端套接字软件来从服务器读取事件。 (例如,流股股票行情)。Android套接字输入流读取(后面是EPIPE)

问题: .read(b);立即返回,值为-1。这会导致无限循环,手机变得非常热。另外,对s.isConnected(),isOpen(),isBound()的所有检查都返回true。本质上插座看起来连接。 (这是一个错误情况,所以.setSoTimeout(x)的任何值都不起作用,12分钟或保留为空.read(b)总是立即返回-1)。

当我稍后写入它时,通过getOutputStream(),我收到一个异常EPIPE(断开的管道)。

以下是核心代码(为简洁起见,省略了日志语句/值检查)。

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); 
} 

如果我在手机上循环使用3G,它可以正常工作。有时它会陷入这种奇怪的状态。

问题

我做错什么了吗?这是预计行为?有没有现有的代码,我可以看看正确方式在Android上进行套接字编程?

回答

2

如果read(byte[], ...)返回< 0,对等体已关闭连接,所以您必须关闭套接字并退出循环。永远不会有更多的数据。

输入流被阻塞,所以read(byte[], ...)可以返回零的唯一方法是如果您指定零长度缓冲区或零长度,具体取决于您调用的超载。因为你不这样做,它永远不会归零。

相反,它会按照它在Javadoc中所说的完成它:返回-1意味着EOS,或者阻塞,直到至少有一个字节的数据可用。

我做错了什么?

几乎所有东西。您的环路测试<= 0完全没有意义,并且完全不正确。测试isConnected()也是如此。这只会告诉你是否曾经连接过Socket。它不随连接状态而改变。 -1的返回码告诉你。你的循环应该阅读:

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

谢谢。似乎我错过了-1表示该流已关闭。当我收到-1时我会推倒。如果我做了socket.setSoTimeout(xx),那么如果超时被击中,我应该接收0个字节,对吧? –

+1

@MichaelSmyers错了。你为什么不阅读Javadoc,而不是所有这些不断猜测?在上述条件下,read()只会返回零,你会在Javadoc中找到它。如果你读取超时,你会得到一个SocketTimeoutException。 – EJP

+0

感谢您的意见。我很感激帮助。 –

1

我使用下面的代码没有问题:

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

好运。

+0

这是我结束了使用的解决方案。我的问题的答案是我接受的那个。 –

0

好吧,我不知道这是否会是这个合适的答案,但我仍然会想给你的代码,它确实效果很好,每次。

请保持它的简单,

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

客户端:

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

服务器端:

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

对于从套接字读取:

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 

} 

用于写入套接字:

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

pw.println("Hello"); 
+1

你为什么要初始化'String s'?这是毫无意义的:它在下一行被重新分配。 – EJP

相关问题