[英]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.