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

时间:2014-04-09 20:13:57

标签: java android

我想在计算机中创建并运行一个应用程序(在java中),并允许多个用户使用他们的Android设备作为该主应用程序的输入设备。它必须是每个设备的实时。

例如:在训练课程后进行一些跟进练习。用户将自己注册(一种简单的形式,将字符串发送到PC上的主应用程序)然后他们得到一些问题和每个问题作为计时器,所以谁正确,更快地回答得到更好的成绩。

完成这项工作的最佳方法是什么?是的,如果它更容易,连接可以通过互联网/局域网。

1 个答案:

答案 0 :(得分:1)

看起来这有两个部分。第一个是处理用户注册等的数据库系统......为此查看SQL。有很多方法。在将多部手机连接到计算机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进行更多研究。

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

干杯,

威尔