我想在计算机中创建并运行一个应用程序(在java中),并允许多个用户使用他们的Android设备作为该主应用程序的输入设备。它必须是每个设备的实时。
例如:在训练课程后进行一些跟进练习。用户将自己注册(一种简单的形式,将字符串发送到PC上的主应用程序)然后他们得到一些问题和每个问题作为计时器,所以谁正确,更快地回答得到更好的成绩。
完成这项工作的最佳方法是什么?是的,如果它更容易,连接可以通过互联网/局域网。
答案 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进行更多研究。
希望这能为您提供有关服务器 - 客户端模型以及您希望如何使用它的一些想法。
干杯,
威尔