- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在计算机中创建和运行一个应用程序(在 Java 中),并允许多个用户使用他们的 Android 设备作为该主应用程序的输入设备。它必须对每个设备都是实时的。
例如:在训练课后做一些跟进练习。用户会自行注册(一种将字符串发送到 PC 上的主应用程序的简单表格),然后他们会收到一些问题,每个问题都会作为一个计时器,所以谁回答正确且速度更快,就会获得更好的成绩。
完成这项工作的最佳方法是什么?是的,如果这样更容易,连接可以通过互联网/局域网。
最佳答案
看起来这有两个部分。第一个是处理用户注册等的数据库系统...查看 SQL。有很多方法。就将多部手机连接到一台电脑而言,您需要一个可以处理线程的服务器和一个手机客户端。
服务器需要服务器套接字。服务器套接字一次可以接受多个连接的客户端。线程服务器可能如下所示:
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();
}
}
通知流是从套接字创建的。这就是打开与客户的沟通 channel 。该线程可以发送一个接收数据和请求。您写什么请求以及处理它们的方式由您决定。
客户端看起来与服务器非常相似,但有一个很大的不同。客户端需要初始化握手。一方必须首先发送数据以初始化通信。由于客户端连接到服务器,我通常让客户端发送第一组数据。客户端的连接代码可能类似于此方法:
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();
}
}
此时你应该有一个客户端连接到服务器并且客户端应该已经初始化了握手。您的流在两端相互开放,允许服务器和客户端进行通信。在这一点上,您可以开始完善和构建服务器和客户端来执行您真正想要执行的操作。我提供的代码缺少露水部分,您在根据您的特定需求定制系统时需要填写这些部分。我提供了这个系统作为示例供您遵循。 一些注意事项。请记住,必须有人开始握手才能进行通信。请记住,必须刷新流才能传输数据。此安全模型不适用于公共(public)连接。我严格地试图阻止外部连接成功。如果您需要安全连接,则需要对 SSL 进行更多研究。
希望这能让您对服务器-客户端模型以及您想用它做什么有所了解。
干杯,
将
关于java - 将多个 android 设备连接到 "main"pc 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22973045/
我正在通过 labrepl 工作,我看到了一些遵循此模式的代码: ;; Pattern (apply #(apply f %&) coll) ;; Concrete example user=> (a
我从未向应用商店提交过应用,但我会在不久的将来提交。 到目前为止,我对为 iPhone 而非 iPad 进行设计感到很自在。 我了解,通过将通用PAID 应用放到应用商店,客户只需支付一次就可以同时使
我有一个应用程序,它使用不同的 Facebook 应用程序(2 个不同的 AppID)在 Facebook 上发布并显示它是“通过 iPhone”/“通过 iPad”。 当 Facebook 应用程序
我有一个要求,我们必须通过将网站源文件保存在本地 iOS 应用程序中来在 iOS 应用程序 Webview 中运行网站。 Angular 需要服务器来运行应用程序,但由于我们将文件保存在本地,我们无法
所以我有一个单页客户端应用程序。 正常流程: 应用程序 -> OAuth2 服务器 -> 应用程序 我们有自己的 OAuth2 服务器,因此人们可以登录应用程序并获取与用户实体关联的 access_t
假设我有一个安装在用户设备上的 Android 应用程序 A,我的应用程序有一个 AppWidget,我们可以让其他 Android 开发人员在其中以每次安装成本为基础发布他们的应用程序推广广告。因此
Secrets of the JavaScript Ninja中有一个例子它提供了以下代码来绕过 JavaScript 的 Math.min() 函数,该函数需要一个可变长度列表。 Example:
当我分别将数组和对象传递给 function.apply() 时,我得到 NaN 的 o/p,但是当我传递对象和数组时,我得到一个数字。为什么会发生这种情况? 由于数组也被视为对象,为什么我无法使用它
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界. 这篇CFSDN的博客文章ASP转换格林威治时间函数DateDiff()应用由作者收集整理,如果你
我正在将列表传递给 map并且想要返回一个带有合并名称的 data.frame 对象。 例如: library(tidyverse) library(broom) mtcars %>% spl
我有一个非常基本的问题,但我不知道如何实现它:我有一个返回数据框,其中每个工具的返回值是按行排列的: tmp<-as.data.frame(t(data.frame(a=rnorm(250,0,1)
我正在使用我的 FB 应用创建群组并邀请用户加入我的应用群组,第一次一切正常。当我尝试创建另一个组时,出现以下错误: {"(OAuthException - #4009) (#4009) 在有更多用户
我们正在开发一款类似于“会说话的本”应用程序的 child 应用程序。它包含大量用于交互式动画的 JPEG 图像序列。 问题是动画在 iPad Air 上播放正常,但在 iPad 2 上播放缓慢或滞后
我关注 clojure 一段时间了,它的一些功能非常令人兴奋(持久数据结构、函数式方法、不可变状态)。然而,由于我仍在学习,我想了解如何在实际场景中应用,证明其好处,然后演化并应用于更复杂的问题。即,
我开发了一个仅使用挪威语的应用程序。该应用程序不使用本地化,因为它应该仅以一种语言(挪威语)显示。但是,我已在 Info.plist 文件中将“本地化 native 开发区域”设置为“no”。我还使用
读完 Anthony's response 后上a style-related parser question ,我试图说服自己编写单体解析器仍然可以相当紧凑。 所以而不是 reference ::
multicore 库中是否有类似 sapply 的东西?还是我必须 unlist(mclapply(..)) 才能实现这一点? 如果它不存在:推理是什么? 提前致谢,如果这是一个愚蠢的问题,我们深表
我喜欢在窗口中弹出结果,以便更容易查看和查找(例如,它们不会随着控制台继续滚动而丢失)。一种方法是使用 sink() 和 file.show()。例如: y <- rnorm(100); x <- r
我有一个如下所示的 spring mvc Controller @RequestMapping(value="/new", method=RequestMethod.POST) public Stri
我正在阅读 StructureMap关于依赖注入(inject),首先有两部分初始化映射,具体类类型的接口(interface),另一部分只是实例化(请求实例)。 第一部分需要配置和设置,这是在 Bo
我是一名优秀的程序员,十分优秀!