我有一个蓝牙服务器,它从客户端(手机)接收数据.我正在使用的代码如下
@Override
public void run() {
try {
this.localDevice = LocalDevice.getLocalDevice();
this.localDevice.setDiscoverable(DiscoveryAgent.GIAC);
this.server = (StreamConnectionNotifier) Connector.open(URL);
while(true) {
if(this.connection == null) {
this.connection = this.server.acceptAndOpen();
System.out.println("INFO: Bluetooth client connected");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.openInputStream()));
this.writer = new BufferedWriter(new OutputStreamWriter(connection.openOutputStream()));
String line;
while((line = reader.readLine()) != null) {
if(line.equals("--#do:disconnect")) {
break;
}
System.out.println("INFO: Received from Bluetooth: " + line);
}
System.out.println("INFO: Client disconnected");
}
}
} catch(BluetoothStateException ex) {
ex.printStackTrace();
} catch(IOException ex) {
ex.printStackTrace();
}
}
如您所见,我有一个不定式循环来接收消息,直到被告知停止为止.目前,循环接收到所有消息.这是有问题的.使用代码的类是MVC中的模型类.在该类中,我还有一个名为getContacts()的方法.它用于通过蓝牙从电话接收联系人.当服务器发送-#do:getcontacts时,电话被告知要发送联系人.
我需要做的是在getContacts()方法的ArrayList中获取联系人并将其作为方法的返回值返回,以便控制器可以处理联系人.
public ArrayList<Contact> getContacts() {
ArrayList<Contact> contacts = new ArrayList<>();
// How do I get the contacts in the ArrayList?
return contacts;
}
解决方法:
我会给你一些建议.我的示例不是工作代码,而是适合您的工作基础.
首先,我强烈建议您在服务器中使用线程.每次客户端连接到服务器时,您都会创建一个新线程,其参数包含启动它所需的所有数据:
boolean running = true; //this class variable will allow you to shut down the server correctly
public void stopServer(){ //this method will shut down the server
this.running = false;
}
public void run() {
...
while(running) {
// if(this.connection == null) { // I removed this line since it's unnecessary, or even harmful!
StreamConnection connection = this.server.acceptAndOpen(); //This line will block until a connection is made...
System.out.println("INFO: Bluetooth client connected");
Thread thread = new ServerThread(connection);
thread.start() //don't forget exception handling...
}
}
在ServerThread类中,您实现了以下这些行来处理客户端(未编译的代码,没有异常处理!):
Class ServerThread extends Thread {
StreamConnection connection;
public ServerThread(StreamConnection connection){
this.connection = connection;
}
public void run() {
...
connection.close(); //closing the connection...don't forget exception handling!
System.out.println("INFO: Client disconnected");
}
}
此代码的优点是什么?现在,您的服务器可以同时处理一千个客户端.您已经进行了并行化,这就是服务器通常的工作方式!没有线程的服务器就像没有鞋子的袜子…
其次,如果您有Java客户端和Java服务器,则可以使用一种更简单的方法将对象发送到服务器:ObjectOutputStream / ObjectInputStream.您只需将包含联系人的数组(通常将使用ArraList)发送到服务器,然后读取该数组.这是服务器的代码(同样未编译且没有任何异常处理):
Class ServerThread extends Thread {
StreamConnection connection;
public ServerThread(StreamConnection connection){
this.connection = connection;
}
public void run() {
BufferedInputStream bis = new BufferedInputStream(this.connection.openInputStream());
ObjectInputStream ois = new ObjectInputStream(bis);
ArrayList contacts = (ArrayList) ois.readObject(); //this is a cast: don't forget exception handling!
//You could also try the method ois.readUTF(); especially if you wanna use other non-Java clients
System.out.println("INFO: Received from Bluetooth: " + contacts);
this.connection.close(); //closing the connection...don't forget exception handling!
//ois.close(); //do this instead of "this.connection.close()" if you want the connection to be open...i.e. to receive more data
System.out.println("INFO: Client disconnected");
//here you do whatever you wanna do with the contacts array, maybe add to your other contacts?
}
}
在Java中,每个类都是一个对象,包括ArrayList.并且由于对象的末尾将被视为断开连接,因此您无需执行其他任何操作.
第三:您不仅将上述服务器用于蓝牙连接,而且还将WLAN连接用于aso.然后,您可以轻松地启动不同的线程,如伪代码if(connection.isBluetooth()){//从BluetoothThread创建线程},否则if(connection.isWLAN()){//从WLANsThread创建线程}.我不知道您的应用程序是关于什么的,但是也许有一天您想将其扩展到台式机,所以使用WLAN是正确的选择.另外,由于无论如何是蓝牙还是WLAN,无论如何,您都需要在客户端中建立一个验证(“哪些联系人将被发送到哪个服务器?”),因为蓝牙的范围较小,无法为您提供任何安全性.