socket communications in JFX
Daniel Zwolenski
zonski at gmail.com
Mon Aug 13 02:44:15 PDT 2012
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