使用UDP(DatagramSocket)执行时抛出异常的AsyncTask太多

时间:2015-11-19 20:05:17

标签: java android android-asynctask udp motionevent

我的“远程”应用程序出了问题。我想要做的是使用我的手机作为触摸屏控制我的电脑的鼠标光标,这是迄今为止的工作,小问题是在光标移动太多后,我得到一个例外。

以下代码只包含最重要的代码段。

在我的手机上,我有以下“触摸屏” - 区域:

RelativeLayout mouse = (RelativeLayout) findViewById(R.id.relative_layout_mouse);
    mouse.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent e) {
            int action = e.getAction();
            if (action == MotionEvent.ACTION_MOVE) { 
                int historySize = e.getHistorySize();
                if(historySize > 0){
                    //calculations on how to get x and y differences between current x/y and previous (historySize-1) x/y
                    new ClientUDPTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new String[]{difference_x, difference_y});
                }
            }
            return true;
        }
    });

当鼠标移动时,会向我的AsyncTask发送许多小的协调更改:

public class ClientUDPTask extends AsyncTask<String,String,String> {
@Override
protected String doInBackground(String[] params) {
    ByteBuffer buffer = ByteBuffer.wrap(new byte[7]);
    //put the coordinates into the ByteBuffer...
    byte[] bytes = buffer.array();
    InetAddress adress = null;
    DatagramSocket socket = null;
    try {
        socket = new DatagramSocket();
        adress = InetAddress.getByName("192.168.1.108");
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length, adress, 9000);
        socket.send(packet);
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

然后在我的服务器上使用它们来移动光标:

public class UDPServer {

private DatagramSocket socket;

public void listen() {
    try {
        socket = new DatagramSocket(9000);
        byte[] buffer = new byte[7];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        while (true) {
            try {
                socket.receive(packet);
                byte[] data = packet.getData();
                //get coordinates out of bytearray...
                Robot robot = new Robot();
                int newX = x - Integer.valueOf(x);
                int newY = y - Integer.valueOf(y);
                robot.mouseMove(newX, newY);
            } catch (AWTException e) {
                e.printStackTrace();
            }
        }
    } catch (SocketException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

现在,正如您所猜测的那样,当鼠标移动很多时,会创建许多任务,将这些数据片段发送到服务器,直到我得到此异常:

java.net.SocketException: socket failed: EMFILE (Too many open files)
    at libcore.io.IoBridge.socket(IoBridge.java:623)
    at java.net.PlainDatagramSocketImpl.create(PlainDatagramSocketImpl.java:93)
    at java.net.DatagramSocket.createSocket(DatagramSocket.java:157)
    at java.net.DatagramSocket.<init>(DatagramSocket.java:80)
    at java.net.DatagramSocket.<init>(DatagramSocket.java:65)
    at com.example.johnsmith.remote.ClientUDPTask.doInBackground(ClientUDPTask.java:31)
    at com.example.johnsmith.remote.ClientUDPTask.doInBackground(ClientUDPTask.java:15)
    at android.os.AsyncTask$2.call(AsyncTask.java:288)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: socket failed: EMFILE (Too many open files)
    at libcore.io.Posix.socket(Native Method)
    at libcore.io.BlockGuardOs.socket(BlockGuardOs.java:282)
    at libcore.io.IoBridge.socket(IoBridge.java:608)
    ... 11 more

此例外指向:

socket = new DatagramSocket();
ClientUDPTask.java

中的

在移动过程中,LogCat显示网络使用量约为1 KB / s。这一切都适用于我的WiFi。

在我使用TCP而不是UDP之前,我已经遇到过这个问题。虽然我也没有使用.executeOnExecutor(...),但速度非常慢。 Playstore上有无数的应用程序可以做这个Remote-Thingie并且它非常流畅,但它们是如何做到的?

我的错误是什么?

1 个答案:

答案 0 :(得分:0)

尝试在客户端使用单个DatagramSocket,而不是为要发送的每个DatagramPacket创建一个新的DatagramSocket。或者使用socket.close();完成套接字后关闭套接字。我想你只是打开太多套接字。