socket communications in JFX

Daniel Zwolenski zonski at gmail.com
Mon Aug 13 02:46:22 PDT 2012


oops

> Either use two *threads* (one for asynch events and another for
request-response)

That should be use two "*sockets" *not threads.


On Mon, Aug 13, 2012 at 7:44 PM, Daniel Zwolenski <zonski at gmail.com> wrote:

> Hey guys,
>
> Sorry for the rough reply earlier. This is actually probably a question
> best for the forums, and if this doesn't provide what you need I'd suggest
> moving the conversation over to there (and let me know, as I don't hit the
> forums as often as I'd like to).
>
> The Worker/Task/Service stuff is useful when your action originates from
> within the UI (such as from a Button click) and you then want to do a long
> running task (like sending data to the server).
>
> For listening to asynchronous messages from the server (i.e. random events
> sent down the socket), everything is reversed: your action is triggered by
> the server and you want to update your UI. For this, I would use a normal
> Java thread with a loop that reads from the socket's input stream and then
> "calls out" to your GUI to update it. The call out is the bit that needs to
> happen in the JFX thread, so you need to wrap this in a Platform.runLater.
>
> Here's some very rough code that does more or less what you want (I've
> used an ObjectReader and assumed the server is serializing Java Objects
> down the wire) but you could stream anything (bytes, XML, JSON, etc).
>
>     public void listenToServer() {
>
>         try {
>             Socket socket = new Socket("myserver.com", 9000);
>             ObjectInputStream in = new
> ObjectInputStream(socket.getInputStream());
>
>             Object next;
>             while ((next = in.readObject()) != null) {
>                 final Object messageFromServer = next;
>                 Platform.runLater(new Runnable() {
>                     public void run() {
>                         handleServerMessage(messageFromServer);
>                     }
>                 });
>             }
>         } catch (IOException e) {
>             // probably some retry attempts - depends on what you are doing
>         } catch (ClassNotFoundException e) {
>             // server sent a dodgy message
>             e.printStackTrace();
>         }
>     }
>
>     public void handleServerMessage(Object messageFromServer) {
>         // you can now update your GUI in the JFX main thread
>         if (messageFromServer instanceof PlayerMoved) {
>             PlayerMoved playerMoved = (PlayerMoved)messageFromServer;
>             playerSprite.moveTo(playerMoved.getX(), playerMoved.getY());
>         } else if (messageFromServer instanceof GameOverMessage) {
>             my.setText("Game Over Man");
>         }
>     }
>
> Note that this is for *listening* (and I'm assuming you are using an
> asynchronous message approach - where your server can send arbitrary
> messages at any time). For *sending* to the server then the Task (or
> Service) stuff is the way to go.
>
>     public void sendMessageToServer(final Object message) {
>         Task worker = new Task() {
>             protected Object call() throws Exception {
>                 // where 'out' is the OutputStream of the Socket
>                 out.writeObject(message);
>                 return null;
>             }
>
>             protected void succeeded() {
>                 // message got through, yay
>             }
>
>             protected void failed() {
>                 // message failed, curse you unreliable internet
>                 getException().printStackTrace();
>             }
>         };
>         new Thread(worker).start();
>     }
>
> If you want to do synchronous messaging (i.e. where you server responds to
> the message you sent it), then you need to be careful with threads. The
> 'succeeded' method above can read the next response from the server, but
> the other listener thread will likely intercept it first (or you might get
> a random message coming down while you are waiting for your response).
> Either use two threads (one for asynch events and another for
> request-response) or put IDs on your request+response and match them up on
> the client using queues, etc.
>
> Also use the Task stuff when first setting up your connection to the sever
> (i.e. when you new the Socket and open the input/output stream). Much the
> same as above.
>
> On a side note, there's some cool stuff with WebSockets now (
> http://tomcat.apache.org/tomcat-7.0-doc/web-socket-howto.html) if you can
> use a server new enough. Avoids lots of nasty port/firewall issues.
>
> Oh and also consider Hessian for serializing really nice small data down
> the wire that can be read by lots of languages (for when you do that iPhone
> version): http://hessian.caucho.com/
>
>
>
>
> On Mon, Aug 13, 2012 at 2:14 PM, Daniel Zwolenski <zonski at gmail.com>wrote:
>
>> Hey Jose,
>>
>> I will reply properly later when I get home, but in general you can do
>> normal Java socket stuff in JFX2.
>>
>> I wouldn't use the Task/Worker stuff for this but make use of the
>> low-level Platform.runLater method.
>>
>> i.e. Start a new thread that reads from the thread, when you get some
>> data you want to process just use Platform.runLater()
>>
>> roughly:
>>
>> new Thread() {
>>
>>    run() {
>>
>>     while (data = socket.readNext()) {
>>
>>         Platform.runLater(new Runabble() {
>>             // update JavaFX UI with 'data' read from socket
>>         }
>>
>>     }
>>
>>
>>   }
>>
>> }
>>
>>
>>
>> On Mon, Aug 13, 2012 at 11:53 AM, Jose Martinez <jmartine_1026 at yahoo.com>wrote:
>>
>>> Jonathon,
>>>
>>> Thank you.  I will digest this info and respond back with any questions.
>>>
>>> jose
>>>
>>>
>>> ________________________________
>>>  From: Jonathan Giles <jonathan.giles at oracle.com>
>>> To: openjfx-dev at openjdk.java.net
>>> Sent: Sunday, August 12, 2012 9:33 PM
>>> Subject: Re: socket communications in JFX
>>>
>>> The generally accepted approach is to keep the slow running tasks off of
>>> the UI thread (in our case the JavaFX Application Thread). If you don't,
>>> you subject the user to a slow user interface, but I'm sure you're well
>>> aware of this based on your comments.
>>>
>>> Generally how you approach this is not defined by JavaFX, rather it
>>> comes down to how your architecture needs to work. One place to look is the
>>> JavaFX Worker and Task API:
>>> http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
>>> http://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html
>>>
>>> -- Jonathan
>>>
>>> On 13/08/2012 1:27 p.m., Jose Martinez wrote:
>>> > Hello,
>>> >
>>> > I am preparing to implement multiplayer capabilities.  Saw one or two
>>> articles out there about socket communications and JFX but they were from
>>> JFX 1.x.
>>> >
>>> > I guess my first question is, is there a way to communicate from a
>>> socket thread directly to the JFX main thread or does the JFX main thread
>>> need to poll some shared object?  Is there any recent documentation out
>>> there on either the topic of socket communications within JFX or even just
>>> multithreading in JFX applications?
>>> >
>>> > thanks!
>>> > jose
>>>
>>
>>
>


More information about the openjfx-dev mailing list