SocketChannel 尚未准备好

问题描述 投票:0回答:2

我再次遇到了 Android 中套接字编程的问题。我的问题是 Selector.select() 返回零,没有 SocketChannels 可供写入。同样的代码在普通 Java 中可以工作,但在 Android 中却不起作用。这是我的代码:

package com.test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class WebSocketTest extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

  SocketChannel channel = null;

        SocketAddress socketAdress = new InetSocketAddress("10.0.0.1", 8787);

  try {
   channel = SocketChannel.open();
  } catch (IOException e) {
   Log.e("ERROR", "channel open");
  }

  try {
   channel.configureBlocking(false);
  } catch (IOException e1) {
   Log.e("ERROR", "channel blocking");
  }

  try {
   channel.connect(socketAdress);
  } catch (IOException e) {
   Log.e("ERROR", "channel connect");
  }

  try {
   while(!channel.finishConnect())
   {

   }
  } catch (IOException e1) {
   Log.e("ERROR", "channel finishConnect");
  }


  Selector selector = null;
  try {
   selector = Selector.open();
  } catch (IOException e) {
   Log.e("ERROR", "selector open");
  }
  try {
   channel.register(selector, channel.validOps());
  } catch (ClosedChannelException e) {
   Log.e("ERROR", "channel register");
  }

  boolean i = true;

  while(i)
  {
   int readyChannels = 0;
   try {
    readyChannels = selector.select();
   } catch (IOException e) {
    Log.e("ERROR", "selector select");
   }

   if(readyChannels > 0)
   {
    i = false;
   }
  }
    }
}

在Java中readyChannels = 1。在Android中它是0。 有人可以帮助我吗?

java android sockets nio
2个回答
2
投票

模拟器位于虚拟路由器后面。您需要配置网络重定向(端口转发)以使模拟器上的某个端口对外部网络(包括您的计算机)可见。


0
投票

此 NIO 代码存在几个问题。

  1. 您应该在进入非阻塞模式之前进行连接,而不是连接然后旋转

    finishConnect()
    (可能永远)。此刻你只是烧毁CPU,压扁电池等等。

  2. 只有当您有东西要写时才应该注册

    OP_WRITE
    。它通常已“准备就绪”,因此如果您永久为其注册频道,您的选择循环就会旋转。
    OP_WRITE
    唯一未准备好的时间是当您填满套接字发送缓冲区时。

© www.soinside.com 2019 - 2024. All rights reserved.