I'm looking to write a small client-server-based text game that handles multiple client connections and persistently affects a game state. I'm wondering what the best way would be to handle multiple connects such that commands are processed in the order they arrive at the server.
Ideally I'm not looking to take advantage of multi-threading, at least on the command processing level. I would be okay with each client having a separate thread (in order to have blocking IO on each thread), as long as I could unify the processing in a single thread thereafter.
Since the only communication between the client and server will be text, I'm not sure how best to go about setting up the communication. If I chose blocking IO, how would I get queue the processing to occur in a single thread?
Alternatively, if I choose non-blocking IO and use a selector to query for when clients have written to the server, how can I get read a String of unknown/unlimited length without using a set-size ByteBuffer? Non-blocking also favours keeping the processing in a single thread as it can just read from the client connections as and when they send new data. However, when I tried to implement it with read/writeUTF I came up against the IllegalBlockingModeException heh.
Any answers to the questions or suggestions on how to do this in a way I haven't mentioned would be sincerely appreciated! I'm fairly new to clients and servers so I don't know whether java.io or java.nio would be most appropriate.
Sorry for the convoluted question. I think I ran away with myself.
Opinions differ, but I'd definitely go with a single thread per client. The communication to the single processing thread could then go via a LinkedBlockingQueue, or just a synchronized LinkedList.
Something like this on the per-client thread:
public class Client implements Runnable, ResponseOutput {
private final BufferedReader br;
private final PrintWriter pw;
public Client(Socket s) {
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
pw = new PrintWriter(s.getOutputStream());
}
// defined by the ResponseOutput interface
public void sendReply(String reply) {
pw.println(reply);
}
public void run() {
try {
while (true) {
String s = br.readLine();
if (s==null)
break;
Processor.queue(new Processor.InputItem(this, s));
}
} catch (IOException ioe) {
... error handling ...
}
}
}
Then this for the processing:
public class Processor implements Runnable {
static public class InputItem {
final ResponseOutput client;
final String command;
public InputItem(ResponseOutput client, String command) {
this.client = client;
this.command = command;
}
}
static private Processor instance;
static public void queue(InputItem item) {
instance.commandQueue.add(item);
}
private BlockingQueue<InputItem> commandQueue;
public void run() {
try {
while (true) {
InputItem item = commandQueue.take();
String reply = doStuff(item.command);
item.client.sendReply(reply);
}
} catch (InterruptedException ie) {
... error handling ....
}
}
}
Within the InputItem class, you can also include a reference to any game state that needs updating. Since there's only the processing thread changing it, you get to do that without any synchronization.
i'm no expert in sever client systems but I'll share a couple of tips
Depending on your need you could simply set up a Tomcat server and do http request, its fairly straight forwards and of course all in Java.
the downside is that the request might be a bit slow.
The Second option you can check out is RMI.
The concept is simple you connect to another computer and when that is done you call methods on the other computer from a local object in you code.
http://java.sun.com/developer/onlineTraining/rmi/RMI.html
it might look a bit complicated (and sometimes debbuging a stack through multiple computer is a bit tricky) but I recommend because it keeps your code clear.
Finally you can try sockets but there your on your own :P
Related
I am programming a multi-threaded server and I have a thread for every client-socket-connection.
I want to pass data from the main thread back and forth to the client-threads.
How many threads do I have to set up?
Does it work like this:
[Server Class:]
private PipedInputStream serverInputStream = new PipedInputStream();
private PipedOutputStream serverOutputStream = new PipedOutputStream();
public PipedInputStream clientInputStream = new PipedInputStream();
public PipedOutputStream clientOutputStream = new PipedOutputStream();
serverInputStream.connect(clientOutputStream);
clientInputStream.connect(serverOutputStream);
or do I have to set up a these four of Streams for each client?
I apologize if this question is maybe dumb, but I have seen that as a possebility and tried it.
If there is a much better way to handle communication between threads then please educate me!
I have written a small Class that waits for a Buffered Reader that blocks and add the messages to the queue:
public class DataListener implements Runnable {
private InputStream is;
private ConcurrentLinkedQueue<String> messages;
private boolean closed = false;
public DataListener(InputStream is, ConcurrentLinkedQueue<String> messages) {
this.is = is;
this.messages = messages;
}
#Override
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while (!closed) {
try {
messages.add(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void close() {
closed = true;
}
}
Can you tell me if that is a good way of working around a blocking listener?
It is definitely not a good idea to use streams to pass data from one thread to another, because:
Stream IO are blocking operations, which would put the thread on hold.
Streams (in general) are not thread-safe by default, which could lead to all kinds of issues.
If you want to pass data between threads frequently try to avoid blocking at all cost, because otherwise the server thread will be waiting most of the time. Java offers a wide tool-set of non-blocking data exchange functionality that you can use instead, which you can find in the Concurrent Package.
A very simple yet effective and fast way to exchange data is to use a message-style system:
final ConcurrentLinkedQueue<MyMessageClass> messages = new ConcurrentLinkedQueue<MyMessageClass>();
public void addMessage(final MyMessageClass message) {
messaged.add(message);
}
protected void serverLoop() {
//...
final MyMessageClass message = messages.poll(); // does not block, returns null if none is available
if (message != null) {
handleMessage(message);
}
//...
}
You can use other classes like the LinkedBlockingQueue for additional features like temporary blocking.
However: when it comes to threading most problems can only be solved by using the correct architecture for your problem at hand. There is no "golden hammer" solution for all your threading tasks, if you want your code to run flawlessly, you need to find the appropriate solution.
You can only use any given piped steam pair between two threads. You will need a pair of pioed streams per thread pair. Don't do this. Use a queue.
I've just got my feet wet with multi-threading and its really awesome. I find myself trying to figure out new ways I can use it make things better and I think I found one but I'm unsure how to design the program for this.
Here's the situation. I have a queue server that multiple clients consume and produce data to but to kick start the process I run a java program on to put some initial data for them to start. then my program is done and I have excess capacity on the queue server but nothing is really running on it. So I want to try to do some maintenance tasks, run a service, and do low priority stuff.I'm not sure how do that though. How do I design a program that does completely different tasks concurrently?
Typically I just wrap my programs in a while (true) loop and it does a single task and I realize I cannot do two while loops at the same time in the same process(maybe nested?). To show a simplified example, I put a bunch of code that runs a runnable(maybe it'll process a low priority queue) and a service that monitors a socket and replies back(I might want to add more depending on cpu usage). How do I get them all to work together? Is there a better way to design it(I know long term its probably better to run multiple java processes but right now I am just trying to manage a single file and I suspect there's a way to give the socket service a higher priority than processing the queue within the file but if they are both running in different files I don't know how to lower one over the other instead of them fighting for resources)?
Thanks and I'll edit this question if it turns out I'm explaining this totally wrong. But in a nutshell, I want it to provide a service to other systems(server socket, in the example) and when its idle I want it to do a few other tasks.
Example(if you understand what I'm asking this code may not be necessary to read):
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class multipleThreads {
private ServerSocket server;
private int port = 7777;
public void ServerSocketExample() {
try {
server = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("starting");
ServerSocketExample example = new ServerSocketExample();
example.handleConnection();
while (true) {
//monitor low low priority queue
}
}
public void handleConnection() {
System.out.println("Waiting for client message...");
//
// The server do a loop here to accept all connection initiated by the
// client application.
//
while (true) {
try {
Socket socket = server.accept();
new ConnectionHandler(socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ConnectionHandler implements Runnable {
private Socket socket;
public ConnectionHandler(Socket socket) {
this.socket = socket;
Thread t = new Thread(this);
t.start();
}
public void run() {
try
{
//
// Read a message sent by client application
//
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
String message = (String) ois.readObject();
System.out.println("Message Received: " + message);
//
// Send a response information to the client application
//
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Hi...");
ois.close();
oos.close();
socket.close();
System.out.println("Waiting for client message...");
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class MonitorQueue implements Runnable{
#Override
public void run() {
// TODO Auto-generated method stub
//do work when stuff comes in the queue
}
}
I strongly recommend you take a look at this project: Java Concurrent Animated. I found this probably the best way to get my head around concurrency concepts in Java: it's animated, interactive, and you can just take one concept at a time and get a good understanding.
http://sourceforge.net/projects/javaconcurrenta/
Take a look at the java.util.concurrent package. It's full off goodies for doing exactly the kinds of things you describe.
In particular, check out the Executors factory class which lets you build Thread Pools that allow multiple tasks to be scheduled and run concurrently on any number of Threads you specify.
Oracle has some great tutorials on using Executors:
http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html
http://docs.oracle.com/javase/tutorial/essential/concurrency/exinter.html
Concurrency is hard, you can read Java Concurrency in Practice, but even the experts have difficulties.
Look for a training course in your area.
I would like to recommend Concurrency Specialist Courses which is based on Java Concurrency in Practice and endorsed by the author, Brian Goetz
I'm developing a network application and I want to get unit testing right. THIS time we'll do it, you know? :)
I'm have trouble testing network connections, though.
In my application I use plain java.net.Sockets.
For example:
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Message {
byte[] payload;
public Message(byte[] payload) {
this.payload = payload;
}
public boolean sendTo(String hostname, int port) {
boolean sent = false;
try {
Socket socket = new Socket(hostname, port);
OutputStream out = socket.getOutputStream();
out.write(payload);
socket.close();
sent = true;
} catch (UnknownHostException e) {
} catch (IOException e) {
}
return sent;
}
}
I read about mocking but am not sure how to apply it.
If I was to test the code, I'd do the following.
Firstly, refactor the code so that the Socket isn't directly instantiated in the method you want to test. The example below shows the smallest change I can think of to make that happen. Future changes might factor out the Socket creation to a completely separate class, but I like small steps and I don't like making big changes on untested code.
public boolean sendTo(String hostname, int port) {
boolean sent = false;
try {
Socket socket = createSocket();
OutputStream out = socket.getOutputStream();
out.write(payload);
socket.close();
sent = true;
} catch (UnknownHostException e) {
// TODO
} catch (IOException e) {
// TODO
}
return sent;
}
protected Socket createSocket() {
return new Socket();
}
Now that the socket creation logic is outside of the method you are trying to test, you can start to mock things up and hook into the creation the socket.
public class MessageTest {
#Test
public void testSimplePayload() () {
byte[] emptyPayload = new byte[1001];
// Using Mockito
final Socket socket = mock(Socket.class);
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
when(socket.getOutputStream()).thenReturn(byteArrayOutputStream);
Message text = new Message(emptyPayload) {
#Override
protected Socket createSocket() {
return socket;
}
};
Assert.assertTrue("Message sent successfully", text.sendTo("localhost", "1234"));
Assert.assertEquals("whatever you wanted to send".getBytes(), byteArrayOutputStream.toByteArray());
}
}
Overriding individual methods on units you want to test is really useful for testing, especially in ugly code with horrible dependencies. Obviously the best solution is sorting out dependencies (in this case I would think that a Message not depend on a Socket, maybe there is a Messager interface as glowcoder suggests), but it's nice to move towards the solution in the smallest possible steps.
I'm going to answer your question as asked instead of redesigning your class (others have that covered, but the basic question on the class as written is stil valid).
Unit testing never tests anything outside the class being tested. This hurt my brain for a while--it means unit test does not in any way prove that your code works! What it does is prove that your code works the same way it did when you wrote the test.
So that said you want a unit test for this class but you also want a functional test.
For the unit test you have to be able to "Mock out" the communications. To do this instead of creating your own socket, fetch one from a "Socket factory", then make yourself a socket factory. The factory should be passed in to the constructor of this class you are testing. This is actually not a bad design strategy--you can set the hostname and port in the factory so you don't have to know about them in your communication class--more abstract.
Now in testing you just pass in a mock factory that creates mock sockets and everything is roses.
Don't forget the functional test though! Set up a "test server" that you can connect to, send some messages to the server and test the responses you get back.
For that matter, you probably want to do even deeper functional tests where you write a client that sends the REAL server some scripted commands and tests the results. You probably even want to create a "Reset state" command just for functional testing. Functional tests actually ensure that entire "Functional units" work together as you expect--something that many unit testing advocates forget.
I'm not going to say this is a bad idea.
I am going to say it can be improved upon.
If you're sending across a raw byte[] over your socket, the other side can do whatever it wants with it. Now, if you're not connecting to a Java server, then you might NEED to do that. If you're willing to say "I'm always working with a Java server" then you can use serialization to your advantage.
When you do this, you can mock it by just creating your own Sendable objects as if they came across the wire.
Create one socket, not one for every message.
interface Sendable {
void callback(Engine engine);
}
So how does this work in practice?
Messenger class:
/**
* Class is not thread-safe. Synchronization left as exercise to the reader
*/
class Messenger { // on the client side
Socket socket;
ObjectOutputStream out;
Messenger(String host, String port) {
socket = new Socket(host,port);
out = new ObjectOutputStream(socket.getOutputStream());
}
void sendMessage(Sendable message) {
out.writeObject(message);
}
}
Receiver class:
class Receiver extends Thread { // on the server side
Socket socket;
ObjectInputStream in;
Engine engine; // whatever does your logical data
Receiver(Socket socket, Engine engine) { // presumable from new Receiver(serverSocket.accept());
this.socket = socket;
this.in = new ObjectInputStream(socket.getInputStream());
}
#Override
public void run() {
while(true) {
// we know only Sendables ever come across the wire
Sendable message = in.readObject();
message.callback(engine); // message class has behavior for the engine
}
}
}
It's difficult testing connection and server interactions.
Tipically, I isolate business logic from communication logic.
I create scenarios for unit tests on business logic, these tests are automatic (use JUni,t and Maven) and i create other scenarios to test real connections, I don't use framework like JUnit for these tests.
In last year I've used Spring Mocks to test logic with HttpResponse HttpRequest, but I think this is not useful.
I follow this question.
Bye
I have a multi-user application consisting of a flex client and blazeds/Spring/java backend - I have the main elements working fine ie. sending messages to destination, consuming and producing. Flex clients are able to send and retrieve a string from this class no problem. What I want to do is to have the 2 clients with access to the same variable..in this crude sample I'm sending a guid from each swf which I append to a string _players server side. What happens is when I launch Swf A, it recieves its guid back fine, as does Swf B. Then Swf A recieves the guid from Swf B, but Swf B does not recieve Swf A. BTW this is the same swf code just launched twice each in a different browser.
Can anyone see where I'm going wrong or what might be a better solution?
public class GameFeed {
private static GaneFeedThread thread;
private final MessageTemplate template;
public GameFeed(MessageTemplate template) {
this.template = template;
}
public void start() {
if (thread == null) {
thread = new GaneFeedThread(this.template);
thread.start();
}
}
public void stop() {
thread.running = false;
thread = null;
}
public static class GaneFeedThread extends Thread {
public boolean running = false;
private final MessageTemplate template;
public GaneFeedThread(MessageTemplate template) {
this.template = template;
}
private static String _players;
public void addPlayer(String name)
{
_players += name + ",";
}
while (this.running) {
this.template.send("game-feed", _players);
}
You have a threading problem in you class. It is not sure if this is the cause of your problem - but it could.
It seams that you are sharing data though the _player variable. But this variable is not thread safe. It has two major problem:
issue 1 : If two clients invoke the addPlayer method at the same time - it is not clear what happen to your player variable - alt least you could have something like a lost update
issue 2: (this is maybe the cause) - The Java memory model does not guarantee that the _player variable is updated in both threads without proper concurrency management.
To fix it you have to do two things:
first: wrap _players += name + ","; in an synchronized block (for issue 1)
second: mark _players as volatile (for issue 2)
#see http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html
It's probably the server that's preventing this. Traditionally, data that is to be shared between clients, or otherwise persisted, is written to a DB or some other datasource. You might do well with a in memory DB. Most web servers have one configured out of the box using HSQLDB or Derby.
A general other solution would be using a thread save collection instead of the String, but this my lead to other problems and is not so efficent like your string.
But nevertheless you should rething your decision: to use a static variable in a Thread class to store shared business data like your player list.
I'm using Beanshell as an embedded debugging tool in my app. It means I can telnet to my app and poke around with its internals while it is running (I typically wrap the telnet session with rlwrap).
The problem is that the only way I've found to print to the Beanshell console, rather than stdout of the application itself, is the print() method within Beanshell.
But I'd like to write code in Java that I can call from Beanshell, which will output to the Beanshell console - ie. it will be shown in my telnet session, not sent to stdout of the application, as happens if you try to use System.out or System.err.
Is this possible?
edit: To further clarify, I'm setting up a Beanshell server as follows:
public static void setUpBeanshell() {
try {
i.setShowResults(true);
i.eval(new InputStreamReader(Bsh.class.getResourceAsStream("init.bsh")));
i.eval("server(" + Main.globalConfig.beanShellPort + ");");
} catch (final EvalError e) {
Main.log.error("Error generated while starting BeanShell server", e);
}
}
How would I modify this such that I can write a Java function that outputs to the telnet session (rather than to System.out of my application)
I'll copy it there as it seems that comments are disregarded this days.
you can:
instead of having a method which print debug information to the standard output returns that debug information:
class ClientList {
Integer clients = 0;
public String debugClientList() {
return clients.toString();
}
and then calling it from beanshell
print(clients.debugCientList());
will give you an output on your telnet
or if you need it more logger like, you need to interact with the Interpreter object directly
InterpreterSingleton {
public static final void Console console = new Interpreter();
}
....
class ClientList {
Integer clients = 0;
public void addClient(Client c) {
....
InterpreterSingleton.console.print("Client added, clients now are " + clients);
}
I'm replying there to the comment as it will need some more coding; the telnet implementation uses a different interpreter for each connection, so you have to expose that interpreter to the objects for printing to the telnet client. The quickest way is to change some bit in the default telnet server and use the modified one to start your server, instead of using the server() scripted command (it's under lgpl or sun license terms)
note that this way have an interpreter started for each connection; the easy and quick fix is to maintain a list of all the running interpreters and print to each one the debugging information, so:
class InterpreterSingletonList {
public static final void Set<Interpreter> is = new HashSet();
void printToAll(String s) {
for (Interpreter i: is) {
i.print(s);
}
}
}
package bsh.util;
import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;
import bsh.*;
/**
BeanShell remote session server.
Starts instances of bsh for client connections.
Note: the sessiond effectively maps all connections to the same interpreter
(shared namespace).
*/
public class Sessiond extends Thread
{
private ServerSocket ss;
NameSpace globalNameSpace;
public Sessiond(NameSpace globalNameSpace, int port) throws IOException
{
ss = new ServerSocket(port);
this.globalNameSpace = globalNameSpace;
}
public void run()
{
try
{
while(true)
new SessiondConnection(globalNameSpace, ss.accept()).start();
}
catch(IOException e) { System.out.println(e); }
}
}
class SessiondConnection extends Thread
{
NameSpace globalNameSpace;
Socket client;
SessiondConnection(NameSpace globalNameSpace, Socket client)
{
this.client = client;
this.globalNameSpace = globalNameSpace;
}
public void run()
{
try
{
InputStream in = client.getInputStream();
PrintStream out = new PrintStream(client.getOutputStream());
/* this is the one you're looking for */
Interpreter i = new Interpreter(
new InputStreamReader(in), out, out, true, globalNameSpace);
i.setExitOnEOF( false ); // don't exit interp
/*store the interpreter on the list*/
InterpreterSingletonList.is.add(i);
i.run();
/*remove it (i.run() blocks)*/
InterpreterSingletonList.is.remove(i);
}
catch(IOException e) { System.out.println(e); }
}
}
I think it's not possible with out hack..., sorry, adapting the telnet server implementation of BSH.
The class we're looking at is bsh.util.Sessiond. Once started, it opens and maintains a telnet server. When ever it receives a command, it creates a new worker thread, this on creates a new bsh.Interpreter with the correct input and output streams (derived from the socket) and runs the interpreter.
So it makes sense, that only output of interpreted commands is send to the telnet client, because System.out and System.err are not redirected.
But that exactly is what has to be done in your case: redirect System.out and System.err to the sockets output stream before the interpreter runs the command and reset the streams after completion.
I'd suggest, you copy the bsh.util.Sessiond class to something like mybsh.util.DebuggerSessiond, apply the redirection code to the run method of the inner class SessiondConnection and modify bsh/commands/server.bsh to start this 'new' telnet server in addition (or instead of the original one). (I guess, this script starts the servers...)
Source code can be found here: beanshell repository
If all your application's output is written using some logging framework anyways, you could write a custom appender/handler which besides logging to say a file would write to the beanshell console in addition? Possibly enabling and disabling the console-logging after executing some beanshell command.
(I wasn't aware of beanshell before, but it seems useful!)