Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I'll have you some suggestions. My examples are no working code, just a working base for you.</p> <p>First, I strongly suggest you to use threads in a server. Everytime a clients connects to the server, you create a new thread, with parameters containing all data needed to start it:</p> <pre><code>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... } } </code></pre> <p>And in the class ServerThread you implement these lines handling the clients (non-compiled code, without exception handling!):</p> <pre><code>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"); } } </code></pre> <p>What is the advantage of this code? Your server is now able to handle a thousand clients at the same moment. You've got parallelisation, and that's how server usually work! A server without threads is like socks without shoes...</p> <p>Second, if you have a Java client and a Java server, you can use a much easier way to send your objects to the server: ObjectOutputStream/ObjectInputStream. You just send the array (I'll use an ArraList as it would be usual) containing the contacts to the server, and then you read the array. Here is the code for the server (again uncompiled and without any exception handling):</p> <pre><code>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? } } </code></pre> <p>In Java, every class is an object, including ArrayList. And since the end of the object will be regarded as the disconnection, you won't need to do anything else.</p> <p>Third: You use above server not only for bluetooth connections, but also for WLAN connections, aso. Then you could easily start different threads, like in pseudo code <code>if(connection.isBluetooth()){//create a thread from BluetoothThread} else if(connection.isWLAN()){//create a thread from WLANsThread}</code>. I don't know what your app is about, but maybe one day you would like to expand it to desktop PC, so using WLAN would be the right thing. Also because you anyway need to build in a verification in the client ("which contacts are going to be sent to which server?"), no matter if it's bluetooth or WLAN, because the low range of buetooth can't give you any security. ;)</p> <p>Fourth, finally about your question: To get something, you need to have a data source and/or a class variable. Here a short example with a file that stores the contacts (but it could also be a database...local or somewhere else!):</p> <pre><code>public class MyApp(){ ArrayList contacts; ... public void run(){ //this happens when we start our app this.contacts = new ArrayList(); FileReader fr = new FileReader ("C:\WhereverYourFileIs\Contacts.file"); BufferedReader br = new BufferedReader(fr); //here you use a loop to read the contacts via "br" from the file and fill them into your array...I can't provide you more code, since the exact data structure is up to you. } //now we want to send our contacts array to the already connected server: public sendArrayToServer() { BufferedOutputStream bos = new BufferedOutputStream (this.connection.openOutputStream()); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this.contacts); //If you use readUTF() in the server, you need to call here something like oos.writeUTF(this.contacts.toString()); or even need to use another parser method which exactly creates the string you want. this.connection.close(); //closing the connection...don't forget exception handling! //oos.close(); //do this instead of "this.connection.close()" if you want the connection to stay open... } } </code></pre> <p>Now in the server you just read out the contacts array as already I described above. What you do with those contacts, remains up to you.</p> <p>Hope this helps you to understand your problems and find a solution. Programming is all about trial &amp; error..and improving your code.</p> <p><strong>EDIT:</strong></p> <p>After our discussion I finally found out what you need: You need a one-thread server called BluetoothManager that interacts with another thread called GUIController. Now since I anyway did the implementation in my head, I can post it for you, together with some explanations. Just note that in this case you don't need to initialize another thread in the server, since the BluetoothManager is already a thread, and you anyway need only one connection at the same moment (the question remains, if that is a "server", I would rather call it a "receiver"):</p> <pre><code>Public class BluetoothManager extends Thread{ boolean running = true; //this class variable will allow you to shut down the server correctly GUIController controller; public BluetoothManager(GUIController controller){ this.controller = controller; //this registers the GUIController in the BluetoothManager } public void stop(){ //this method will shut down the "server" this.running = false; } public void run() { this.localDevice = LocalDevice.getLocalDevice(); this.localDevice.setDiscoverable(DiscoveryAgent.GIAC); this.server = (StreamConnectionNotifier) Connector.open(URL); while(running){ StreamConnection connection = this.server.acceptAndOpen(); //This line will block until a connection is made...or running==false! System.out.println("INFO: Bluetooth client connected"); 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! System.out.println("INFO: Received from Bluetooth: " + contacts); this.connection.close(); //closing the connection...don't forget exception handling! System.out.println("INFO: Client disconnected"); this.controller.refreshContacts(contacts); } } } public class GUIController extends Thread implements Runnable { ArrayList contacts; //also a HashMap may be appropriate BluetoothManager manager; public void run(){ this.contacts = new ArrayList(); FileReader fr = new FileReader ("C:\WhereverYourFileIs\Contacts.file"); BufferedReader br = new BufferedReader(fr); //here you use a loop to read the contacts via "br" from the file and fill them into your array...I can't provide you more code, since the exact data structure is up to you. } public void startBluetoothManager(){ //starting the BluetoothManager this.manager = new BluetoothManager(this); this.manager.start(); } public void abortBluetoothManager(){ //call this when clicking on the "Abort" button this.manager.stop(); //now the next 2 lines you normally don't need...still may use it if you've problems shutting down the thread: // try{ this.manager.interrupt(); } //we want to be 100% sure to shut down our thread! // catch(Exception e){} this.manager = null; //now the garbage collector can clean everything...byebye } public void refreshContacts(ArrayList contacts) { // synchronize(this.contactArray){ //no synchronisation needed if you have a GUI pop-up with an "Abort"-button! Iterator i = this.contacts.iterator(); while(i.hasNext()){ this.contacts.add(i.next()); } //At the end you need remove the "Receiving message" pop-up together with the "Abort Receiving"-button, these are all class variables! // important note: If you have unique entries, you may need to replace them! In this case I suggest storing all contact objects better in a HashMap contacts, and use the unique ID as a key to find the element. And then you may prompt the user, if there are identical entries, to overwrite each entry or not. These things remain all up to you. } } //As always: This is no compiled code!! </code></pre> <p>The GUIController first runs the BluetoothManager with <code>startBluetoothManager()</code> and does nothing else, except showing a notification "Receiving contacts" and an "Abort Reveiving"-button. And when the BluetoothManager is finished, he just adds the new contacts into the existing contacts-array inside the GUIController by calling <code>refreshContacts(...)</code>. If you push the "Abort Reveiving"-button, you immediately call the <code>abortBluetoothManager()</code> method, which sets <code>running=false</code> in the BluetoothManager to end the server and finish the thread.</p> <p>The main problem this solution solves: It's not possible for two threads to directly communicate with each other! Once you call <code>thread.start()</code>, every thread is on its own. That's why there is no possibility for the BluetoothManager-thread to tell the GUIController-thread "I've finished!". The only thing those threads can do, is share the same ressource(s), and communicate via this ressource(s). In our case, it's the <code>contacts</code>-ArrayList in the GUIController, which first I thought needs to be synchronized and can be updated by both threads (but not on the same time). And - kind of funnyness - there is a second shared ressource, it's actually the <code>running</code> flag in the class BluetoothManager which can shut it down (but there is never any synchronisation of <code>running</code> needed, this variable is only changed by the GUIController).</p> <p>Now about the synchronisation: I thought about this problem more and understood, that you can solve your problem also <em>without</em> any "synchronized(...)" call. So, if you don't want to synchronize the ArrayList, you must do it like this: While the server is running, you only show the "Receiving Contacts" pop-up and the "Abort Reveiving"-button. While this happens, you just never access the contact-ArrayList inside the GUIController. This is somehow an "intrinsic synchronisation" which needs no real Java synchronisation. Still you may implement synchronisation, just to be 100% sure that nothing happens if you expand the app in the future.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload