1

我试图在 android 应用程序(作为服务器)和在 windows 上运行的基于 java 的客户端之间实现 tcp 套接字连接。(下面的简短版本,没有代码)

我使用一些传感器监听器来实现游戏运动(每个人都知道这种基于传感器的赛车游戏运动。

我已经为此目的实施了一项服务,该服务是从第一个活动开始的。该服务实现如下(我只是粘贴相关的代码片段,而不是整个类):

public class ServerService extends Service {

    ConnectionHandler conHandler;

    @Override
    public void onCreate() {
        startListener();
    }

    private void startListener() {
        conHandler = new ConnectionHandler(this);
        conHandler.execute();
    }

    private void sendMessage(String s)
    {
        conHandler.write(s);
    }

    public void messageNotify(String s) {
        //Log.d("receivedMessage", s);
    }    
}

ConnectionHandler 类:

public class ConnectionHandler extends AsyncTask<Void, Void, Void>{

    public static int serverport = 11111;
    ServerSocket s;
    Socket c;
    ConnectionListening conListening;
    ConnectionWriting conWriting;
    DataOutputStream dos;
    DataInputStream dis;
    ServerService server;

    public ConnectionHandler(ServerService server)
    {
        this.server = server;
    }

    @Override
    protected Void doInBackground(Void... params) {

        try {
            Log.i("AsyncTank", "doInBackgoung: Creating Socket");
            s = new ServerSocket(serverport);
        } catch (Exception e) {
            Log.i("AsyncTank", "doInBackgoung: Cannot create Socket");
        }
        try {
                    //this is blocking until client connects
            c = s.accept();
            Log.d("ConnectionHandler", "client connected");
            dis = new DataInputStream(c.getInputStream());
            dos = new DataOutputStream(c.getOutputStream());
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
            conWriting = new ConnectionWriting(this.c, this.dos);
            conWriting.execute();
            conListening = new ConnectionListening(this.c, this.dis, this.server);
            if(this.c != null)
            {
                Timer timer = new Timer();
                timer.schedule(conListening, 0, 10);
            }

            Log.i("AsyncTank", "doInBackgoung: Socket created, Streams assigned");
        return null;
    }

    public void write(String s)
    {
        conWriting.writeToStream(s);
    }

    public void messageNotify(String s) {
        // TODO method stub 
    }   

}

ConnectionHandler 与 ConnectionWriting 类似地实现为 AsyncTask,因此 tcp 方法的阻塞不会影响整个通信。客户端能够向服务器发送消息。因为我不知道这条消息什么时候到达,所以我使用每 10 毫秒执行一次的 TimerTask 来检查是否有新消息。

ConnectionWriting 如下所示:

public class ConnectionWriting extends AsyncTask<Context, Void, Boolean>{

    public DataOutputStream dos;
    Socket c;

    public ConnectionWriting(Socket c, DataOutputStream dos) {
        this.dos = dos;
        this.c = c;
    }

    @Override
    protected Boolean doInBackground(Context... params) {
        return true;
    }   

    public void writeToStream(String s) {
        try {
            if (c != null){
                //Log.i("AsynkTask", "writeToStream");
                dos.writeBytes(s+"\n");
                dos.flush();
                Log.i("AsynkTask", "write: " +s);
            } else {
                Log.i("AsynkTask", "writeToStream : Cannot write to stream, Socket is closed");
            }
        } catch (Exception e) {
            Log.i("AsynkTask", "writeToStream : Writing failed");
        }
    }

}

和 ConnectionListening 类: public class ConnectionListening extends TimerTask{

    public DataInputStream dis;
    Socket c;
    ServerService server;

    public ConnectionListening(Socket c, DataInputStream dis, ServerService server)
    {
        this.c = c;
        this.dis = dis;
        this.server = server;
    }

    @Override
    public void run() {
        String message = "";
        try {
            if (c != null) {
                //Log.i("AsynkTask", "readFromStream : Reading message");
                message = dis.readLine();
                Log.i("AsynkTask", "read: " + message);
            } else {
                Log.i("AsynkTask", "readFromStream : Cannot Read, Socket is closed");
            }
        } catch (Exception e) { 
            Log.i("AsynkTask", "readFromStream : Writing failed");
        }

        if(message != null)
        {
            this.server.messageNotify(message);
        }

    }


}

我选择这种复杂的异步方式,因为服务器几乎是连续向客户端发送数据,并且存在客户端必须将数据发送回来的情况。使用 tcp 套接字的传统方式,不可能实现非阻塞通信,这意味着如果服务器正在发送(写入),读取功能阻塞,我永远不会收到客户端消息。

简而言之: 我测试了我的方法,但服务器总是先发送他的数据,然后再获取客户端消息。它不是异步的!?:-/

也许任何人都可以帮助我解决这个问题。或者有没有更简单的方法来实现这种方法?通信必须是异步的!并且必须自动完成读取(我试图用这种轮询方法来实现)。

我读过我可以使用一个线程进行读取,一个线程用于写入,但是我在使用写入功能(不知道如何在正在运行的线程中调用函数)和在我的活动中调用函数时遇到了问题。

我感谢每一个帮助!

问候

4

0 回答 0