繁体   English   中英

将多个Android设备连接到“主” PC应用程序

[英]Connect multiple android devices to a “main” pc app

我想在计算机上创建并运行一个应用程序(以Java编写),并允许多个用户将其android设备用作该主应用程序的输入设备。 每个设备都必须实时。

例如:在培训课程之后进行一些后续练习。 用户将自己注册(一种简单的形式,可以将字符串发送到PC上的主应用程序),然后他们会收到一些问题,每个问题都将作为计时器,因此谁能正确,更快地回答,就可以获得更高的评分。

完成这项工作的最佳方法是什么? 是的,如果使它更容易,则可以通过Internet / LAN进行连接。

看起来有两个部分。 首先是用于处理用户注册等的数据库系统。 有很多方法。 就将多部电话连接到计算机PC而言,您将需要一个可以处理线程的服务器和一个电话客户端。

服务器需要服务器套接字。 服务器套接字一次可以接受多个连接的客户端。 线程服务器可能如下所示:

public class ServerThread extends Thread
{
    //is the thread running
    private boolean running = true;

    //ports for the server sockets
    private final int dataPort;
    private final int filePort;

    private final String certificateDir;
    private final char[] password;

    private Vector<ClientHandlerThread> connectedClients = new Vector<ClientHandlerThread>(20, 5);
    private Properties userProperties = new Properties();

    public ServerThread(int dataPort,
                        int filePort,
                        String certificateDir,
                        char[] password,
                        Properties userProperties)
    {
        this.dataPort = dataPort;
        this.filePort = filePort;
        this.certificateDir = certificateDir;
        this.password = password;
        this.userProperties = userProperties;
    }

    public void run()
    {
        /*
         * We need a server socket that can accept traffic. I use one for file traffic and one
         * for data traffic although one socket could be used.
         */
        SSLServerSocket sslDataTraffic = null;
        SSLServerSocket sslFileTraffic = null;
        SSLServerSocketFactory sslFac = null;

        /*
         * Everything in the following block is related to creating a SSL security manager. 
         * If you don't need validated communications you don't have to use SSL. Just normal
         * sockets.
         */
        try
        {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(new FileInputStream(certificateDir), password);

            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(keyStore);

            KeyManagerFactory kmf = KeyManagerFactory.getInstance((KeyManagerFactory.getDefaultAlgorithm()));
            kmf.init(keyStore, password);

            System.setProperty("https.protocols", "SSL");
            SSLContext ctx = SSLContext.getInstance("SSL");
            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            sslFac = ctx.getServerSocketFactory();
        }
        catch(Exception e)
        {
            System.out.println("FAILED.");
            e.printStackTrace();
            System.exit(-1);
        }

        try
        {
            //create data server socket 
            System.out.print("Creating data socket......... ");
            sslDataTraffic = (SSLServerSocket) sslFac.createServerSocket(dataPort);
            System.out.println("DONE. Est. on:" + dataPort);

            //create file server socket
            System.out.print("Creating file socket......... ");
            sslFileTraffic = (SSLServerSocket) sslFac.createServerSocket(filePort);
            System.out.println("DONE. Est. on:" + filePort);
        }
        catch (IOException e)
        {
            System.out.println("FAILED.");
            System.out.println(e.toString() + " ::: " + e.getCause());
            System.exit(-1);
        }

        /*
         * This block is used to print the ip the server is running on. Easy to incorporate this here
         * so the information doesn't have to be gathered form another source.
         */
        try
        {
            System.out.print("Finishing.................... ");
            Socket s = new Socket("google.com", 80);
            System.out.println("DONE.");
            System.out.println("Server online at: " + s.getLocalAddress().getHostAddress());
            System.out.println("====================*====================");
            s.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        /*
         * This is the block that accepts connections from clients.
         */
        try
        {
            while (running)
            {
                //wait here until a connection is bound to new sockets through the server sockets
                SSLSocket sslDataTrafficSocketInstance = (SSLSocket) sslDataTraffic.accept();
                SSLSocket sslFileTrafficSocketInstance = (SSLSocket) sslFileTraffic.accept();
                //sockets to communicate with the client are created. Lets put them in a thread so 
                //we can continue to accept new clients while we work with the newly and previously
                //connected clients

                //create a new thread
                ClientHandlerThread c = new ClientHandlerThread(
                        sslDataTrafficSocketInstance, 
                        sslFileTrafficSocketInstance, 
                        userProperties);
                //start thread
                c.start();
                //add newly connected client to the list of connected clients
                connectedClients.add(c);
            }
        }
        catch (IOException e)
        {
            System.out.println("Fatal server error, terminating server and client handler threads");

            stopServer();
        }
    }
}

ClientHandlerThread类的构造函数如下所示:

    private PrintWriter writer;
    private BufferedReader reader;
    private InputStream inputStream;
    private OutputStream outputStream;

    public ClientHandlerThread(
            SSLSocket dataSocket,
            SSLSocket fileSocket,
            Properties userProperties)
    {
        this.dataSocket = dataSocket;
        this.fileSocket = fileSocket;

        this.userProperties = userProperties;

        try
        {
            this.reader = new BufferedReader(new InputStreamReader(this.dataSocket.getInputStream()));
            this.writer = new PrintWriter(this.dataSocket.getOutputStream());
            this.inputStream = fileSocket.getInputStream();
            this.outputStream = fileSocket.getOutputStream();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

通知流是从套接字创建的。 这就是打开与客户的沟通渠道的原因。 线程可以发送接收数据和请求。 您要写什么请求以及如何处理它们。

客户端看起来与服务器非常相似,但有很大的不同。 客户端需要初始化握手。 一方必须首先发送数据以初始化通信。 由于客户端正在连接到服务器,因此我通常让客户端发送第一组数据。 客户端的连接代码可能类似于以下方法:

    private void connect()
    {
        try
        {
            SSLSocketFactory sslFac;
            SSLSocket dataSocket = null;
            SSLSocket fileSocket = null;

            /*
             * This block is nearly identical to the security block for the server side.  
             */
            try
            {
                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(new FileInputStream(certificateDir), password.toCharArray());

                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                tmf.init(keyStore);

                KeyManagerFactory kmf = KeyManagerFactory.getInstance((KeyManagerFactory.getDefaultAlgorithm()));
                kmf.init(keyStore, password.toCharArray());

                System.setProperty("https.protocols", "SSL");
                SSLContext ctx = SSLContext.getInstance("SSL");
                ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
                sslFac = ctx.getSocketFactory();

                String ip = "<THE SERVER'S IP ADDRESS>";
                dataSocket = (SSLSocket) sslFac.createSocket(ip, dataPort);
                fileSocket = (SSLSocket) sslFac.createSocket(ip, filePort);
            }
            catch(Exception e)
            {
                System.out.println("FAILED.");
                e.printStackTrace();
                System.exit(-1);
            }

            reader = new BufferedReader(new InputStreamReader(dataSocket.getInputStream()));
            writer = new PrintWriter(dataSocket.getOutputStream());
            OutputStream fileOut = fileSocket.getOutputStream();

            writer.println("CLIENT_HANDSHAKE_INIT");
            writer.flush();
            }
     }

此时,您应该有一个客户端连接到服务器,并且客户端应该已经初始化了握手。 您的两端都有彼此开放的流,从而允许服务器和客户端进行通信。 在这一点上,您可以开始完善并构建服务器和客户端以完成您实际想要做的事情。 我提供的代码缺少露水部分,您在根据特定需求定制系统时需要填写。 我提供了该系统作为示例供您遵循。 一些注意事项。 请记住,有人必须开始握手才能进行通信。 请记住,必须刷新流才能传输数据。 此安全模型不适用于公共连接。 我严格尝试阻止外部连接成功。 如果需要安全连接,则需要对SSL进行更多研究。

希望这能给您一些有关服务器-客户端模型以及您要如何使用它的想法。

干杯,

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM