首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在不同线程上运行AsynchronousSocketChannel

在不同线程上运行AsynchronousSocketChannel
EN

Stack Overflow用户
提问于 2019-02-09 05:50:33
回答 1查看 216关注 0票数 1

我试图使用AsynchronousSocketChannel在Android中通过TCP/IP发送数据,但我得到了android.os.NetworkOnMainThreadException.

当我运行程序并试图连接到服务器时,将执行失败的连接CompletionHandler方法,从而产生一个NetworkOnMainThreadException。

Boost.Asio中,我们在单独的线程中运行io_context。我们在AsynchronousSocketChannel中需要做些什么才能在单独的线程上运行它?

Ethernet.java:

代码语言:javascript
复制
public class Ethernet {
    private String                      ip;
    private int                         port;
    private Queue<String>               recvDataQueue, sendDataQueue;
    private InetSocketAddress           address;
    private String                      readData;
    private InputStream                 in;
    private OutputStream                out;
    private AsynchronousSocketChannel   socket;
    private boolean                     socketAlive, connectionInProgress;
    private ByteBuffer                  readBuffer, sendBuffer;

    Ethernet(String ip, int port) {
        if (port > 65535 && port < 1024)
            port = 6666;
        this.ip = ip;
        this.port = port;
        this.socketAlive = false;
        connectionInProgress = false;
        address = new InetSocketAddress(ip, port);
        this.readBuffer = ByteBuffer.allocate(8192);
    }

    public boolean connect(){
        try{
            if(this.socketAlive)
                return false;
            connectionInProgress = true;
            this.socket = AsynchronousSocketChannel.open();
            this.socket.connect(this.address, null,
                new CompletionHandler<Void, Object>() {
                @Override
                public void completed(Void result, Object attachment) {
                    socketAlive = true;
                    //connectionInProgress = false;
                }
                @Override
                public void failed(Throwable e, Object attachment) {
                    socketAlive = false;
                    //connectionInProgress = false;
                }
            });
            return true;
        }
        catch (Exception e){
            String strErr = e.getMessage();
            Log.e("Exception", strErr);
        }
        return false;
    }

    public long sendData(String writeData){
        try{
            //this.sendBuffer = ByteBuffer.allocateDirect(writeData.length());
            this.sendBuffer = ByteBuffer.wrap(writeData.getBytes(), 0, writeData.length());
            //this.socket.write(writeBuffer, 0, writeData.length()), null,
            this.socket.write(this.sendBuffer, null,
            new CompletionHandler <Integer, Object>() {
                @Override
                public void completed(Integer result, Object attachment) {
                    if (result < 0) {
                        // handle unexpected connection close
                        socketAlive = false;
                        //connectionInProgress = false;
                    }
                    else if(result < sendBuffer.remaining()){
                        // got all data, process the buffer
                        sendBuffer.compact();
                        socket.write(sendBuffer, null, this);    //Test
                    }
                    else{

                    }
                }
                @Override
                public void failed(Throwable e, Object attachment) {
                    if(socket.isOpen()){
                        try{
                            socketAlive = false;
                            socket.close();
                        }
                        catch (Exception ex){
                            String strErr = e.getMessage();
                            Log.e("Exception", strErr);
                        }
                    }
                }
            });
        }
        catch (Exception e){
            String strErr = e.getMessage();
            Log.e("Exception", strErr);
        }
        return -1;
    }

    private void recieveDataSocket() throws Exception {
        this.socket.read(this.readBuffer, null, new CompletionHandler<Integer, Object>() {
            @Override
            public void completed(Integer result, Object attachment) {
                if (result < 0) {
                    socketAlive = false;
                }
                else {
                    //recvQueue.add(readBuffer.toString());
                }
            }
            @Override
            public void failed(Throwable e, Object attachment) {
                if(socketAlive && socket.isOpen()) {
                    try {
                        socketAlive = false;
                        //connectionInProgress = false;
                        socket.close();
                    }
                    catch (final Exception ex){

                    }
                }
            }
        });
    }

    public void disconnect(){
        try {
            if(this.socket.isOpen() && this.socketAlive)
                this.socket.close();
        }
        catch (final Exception ex){
            String strErr = ex.getMessage();
            Log.e("Exception", strErr);
        }
    }

    }
}

MainActivity.java

代码语言:javascript
复制
Ethernet eth = new Ethernet("192.168.1.22", 6666);
while(true) {
    if(!eth.isSocketAlive() && !eth.isConnectionInProgress())
         eth.connect();
    if(!eth.isSocketAlive())
         continue;
    eth.sendData("Hello, World!!!\n");
         eth.disconnect();
}
EN

回答 1

Stack Overflow用户

发布于 2022-01-13 06:10:23

AsynchronousSocketChannel在非阻塞模式下使用SocketChannel,但是Android不检查通道的阻塞模式。以下是一些解释:https://stackoverflow.com/a/52458658/7115065

您应该更新StrictMode以忽略此异常。我会按照下面的方式来做,类似于内置的allowThreadDiskWrites()方法。

代码语言:javascript
复制
StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(oldPolicy).permitNetwork().build());

// ... code

StrictMode.setThreadPolicy(oldPolicy);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54603630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档