What's the best way to implement a non-blocking socket in Java?
Or is there such a thing? I have a program that communicates with a server through socket but I don't want the socket call to block/cause delay if there is a problem with the data/connection.
Java non-blocking socket was introduced in Java 2 Standard Edition 1.4. It allows net communication between applications using the sockets without blocking the processes. But Teo, what a non-blocking socket is?, in which contexts it can be useful?, and how it works? Okay young Padawan lets answer this questions.
What a non-blocking socket is?
A non-blocking socket allows I/O operation on a channel without blocking the processes using it. This means, we can use a single thread to handle multiple concurrent connections and gain an "asynchronous high-performance" read/write operations (some people may not agreed with that)
Ok, in which contexts it can be useful?
Suppose you would like to implement a server accepting diverse client connections. Suppose, as well, that you would like the server to be able to process multiple requests simultaneously. Using the traditional way you have two choices to develop such a server:
a. Implement a multi-thread server that manually handles a thread for each connection.
b. Using an external third-party module.
Both solutions work, but adopting the first one you have to develop the whole thread-management solution, with related concurrency and conflict troubles. The second solution makes the application dependent on a non-JDK external module and probably you have to adapt the library to your necessities. By means of the non-blocking socket, you can implement a non-blocking server without directly managing threads or resorting to external modules.
How it works?
Before going into details, there are few terms that you need to understand:
In NIO based implementations, instead of writing data onto output streams and reading data from input streams, we read and write data from buffers. A buffer can be defined as a temporary storage.
Channel transports bulk of data into and out of buffers. Also, it can be viewed as an endpoint for communication.
Readiness Selection is a concept that refers to “the ability to choose a socket that will not block when data is read or written.”
Java NIO has a class called Selector that allows a single thread to examine I/O events on multiple channels. How is this possible? Well, the selector can check the "readiness" of a channel for events such as a client attempting a connection, or a read/write operation. This is, each instance of Selector can monitor more socket channels and thus more connections. Now, when something happens on the channel (an event occurs), the selector informs the application to process the request. The selector does it by creating event keys (or selection keys), which are instances of the SelectionKey class. Each key holds information about who is making the request and what type of the request is, as shown in the Figure 1.
Figure 1: Structure diagram
A basic implementation
A server implementation consists of an infinite loop in which the selector waits for events and creates the event keys. There are four possible types for a key:
Acceptable: the associated client requests a connection.
Connectable: the server accepted the connection.
Readable: the server can read.
Writeable: the server can write.
Usually acceptable keys are created on the server side. In fact, this kind of key simply informs the server that a client required a connection, then the server individuates the socket channel and associates this to the selector for read/write operations. After this, when the accepted client reads or writes something, the selector will create readable or writeable keys for that client..
Now you are ready to write the server in Java, following the proposed algorithm. The creation of the socket channel, the selector, and the socket-selector registration can be made in this way:
final String HOSTNAME = "127.0.0.1";
final int PORT = 8511;
// This is how you open a ServerSocketChannel
serverChannel = ServerSocketChannel.open();
// You MUST configure as non-blocking or else you cannot register the serverChannel to the Selector.
serverChannel.configureBlocking(false);
// bind to the address that you will use to Serve.
serverChannel.socket().bind(new InetSocketAddress(HOSTNAME, PORT));
// This is how you open a Selector
selector = Selector.open();
/*
* Here you are registering the serverSocketChannel to accept connection, thus the OP_ACCEPT.
* This means that you just told your selector that this channel will be used to accept connections.
* We can change this operation later to read/write, more on this later.
*/
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
First we create an instance of SocketChannel with ServerSocketChannel.open() method. Next, configureBlocking(false) invocation sets this channel as nonblocking. The connection to the server is made by serverChannel.socket().bind() method. The HOSTNAME represents the IP address of the server, and PORT is the communication port. Finally, invoke Selector.open() method to create a selector instance and register it to the channel and registration type. In this example, the registration type is OP_ACCEPT, which means the selector merely reports that a client attempts a connection to the server. Other possible options are: OP_CONNECT, which will be used by the client; OP_READ; and OP_WRITE.
Now we need to handle this requests using an infinite loop. A simple way is the following:
// Run the server as long as the thread is not interrupted.
while (!Thread.currentThread().isInterrupted()) {
/*
* selector.select(TIMEOUT) is waiting for an OPERATION to be ready and is a blocking call.
* For example, if a client connects right this second, then it will break from the select()
* call and run the code below it. The TIMEOUT is not needed, but its just so it doesn't
* block undefinable.
*/
selector.select(TIMEOUT);
/*
* If we are here, it is because an operation happened (or the TIMEOUT expired).
* We need to get the SelectionKeys from the selector to see what operations are available.
* We use an iterator for this.
*/
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
// remove the key so that we don't process this OPERATION again.
keys.remove();
// key could be invalid if for example, the client closed the connection.
if (!key.isValid()) {
continue;
}
/*
* In the server, we start by listening to the OP_ACCEPT when we register with the Selector.
* If the key from the keyset is Acceptable, then we must get ready to accept the client
* connection and do something with it. Go read the comments in the accept method.
*/
if (key.isAcceptable()) {
System.out.println("Accepting connection");
accept(key);
}
/*
* If you already read the comments in the accept() method, then you know we changed
* the OPERATION to OP_WRITE. This means that one of these keys in the iterator will return
* a channel that is writable (key.isWritable()). The write() method will explain further.
*/
if (key.isWritable()) {
System.out.println("Writing...");
write(key);
}
/*
* If you already read the comments in the write method then you understand that we registered
* the OPERATION OP_READ. That means that on the next Selector.select(), there is probably a key
* that is ready to read (key.isReadable()). The read() method will explain further.
*/
if (key.isReadable()) {
System.out.println("Reading connection");
read(key);
}
}
}
You can find the implementation source here
NOTE: Asynchronous Server
An alternative to the the Non-blocking implementation we can deploy an Asynchronous Server. For instance, you can use the AsynchronousServerSocketChannel class, which provides an asynchronous channel for stream-oriented listening sockets.
To use it, first execute its static open() method and then bind() it to a specific port. Next, you'll execute its accept() method, passing to it a class that implements the CompletionHandler interface. Most often, you'll find that handler created as an anonymous inner class.
From this AsynchronousServerSocketChannel object, you invoke accept() to tell it to start listening for connections, passing to it a custom CompletionHandler instance. When we invoke accept(), it returns immediately. Note that this is different from the traditional blocking approach; whereas the accept() method blocked until a client connected to it, the AsynchronousServerSocketChannel accept() method handles it for you.
Here you have an example:
public class NioSocketServer
{
public NioSocketServer()
{
try {
// Create an AsynchronousServerSocketChannel that will listen on port 5000
final AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel
.open()
.bind(new InetSocketAddress(5000));
// Listen for a new request
listener.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>()
{
#Override
public void completed(AsynchronousSocketChannel ch, Void att)
{
// Accept the next connection
listener.accept(null, this);
// Greet the client
ch.write(ByteBuffer.wrap("Hello, I am Echo Server 2020, let's have an engaging conversation!\n".getBytes()));
// Allocate a byte buffer (4K) to read from the client
ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
try {
// Read the first line
int bytesRead = ch.read(byteBuffer).get(20, TimeUnit.SECONDS);
boolean running = true;
while (bytesRead != -1 && running) {
System.out.println("bytes read: " + bytesRead);
// Make sure that we have data to read
if (byteBuffer.position() > 2) {
// Make the buffer ready to read
byteBuffer.flip();
// Convert the buffer into a line
byte[] lineBytes = new byte[bytesRead];
byteBuffer.get(lineBytes, 0, bytesRead);
String line = new String(lineBytes);
// Debug
System.out.println("Message: " + line);
// Echo back to the caller
ch.write(ByteBuffer.wrap(line.getBytes()));
// Make the buffer ready to write
byteBuffer.clear();
// Read the next line
bytesRead = ch.read(byteBuffer).get(20, TimeUnit.SECONDS);
} else {
// An empty line signifies the end of the conversation in our protocol
running = false;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
// The user exceeded the 20 second timeout, so close the connection
ch.write(ByteBuffer.wrap("Good Bye\n".getBytes()));
System.out.println("Connection timed out, closing connection");
}
System.out.println("End of conversation");
try {
// Close the connection if we need to
if (ch.isOpen()) {
ch.close();
}
} catch (I/OException e1)
{
e1.printStackTrace();
}
}
#Override
public void failed(Throwable exc, Void att)
{
///...
}
});
} catch (I/OException e) {
e.printStackTrace();
}
}
public static void main(String[] args)
{
NioSocketServer server = new NioSocketServer();
try {
Thread.sleep(60000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
You can find the full code here
What's the best way to implement a non-blocking socket in Java?
There is only one way. SocketChannel.configureBlocking(false).
Note that several of these answers are incorrect. SocketChannel.configureBlocking(false) puts it into non-blocking mode. You don't need a Selector to do that. You only need a Selector to implement timeouts or multiplexed I/O with non-blocking sockets.
Apart from using non blocking IO, you might find it is much simpler to have a writing thread for your connection.
Note: if you only need a few thousand connections, one to two threads per connection is simpler. If you have around ten thousand or more connections per server you need NIO with Selectors.
java.nio package provides Selector working much like as in C.
I just wrote this code . It works well . This is an example of the Java NIO as mentioned in the above answers but here i post the code .
ServerSocketChannel ssc = null;
try {
ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(port));
ssc.configureBlocking(false);
while (true) {
SocketChannel sc = ssc.accept();
if (sc == null) {
// No connections came .
} else {
// You got a connection. Do something
}
}
} catch (IOException e) {
e.printStackTrace();
}
Related
I'm new at network programming and i have been searching for a solution to my problem here but couldn't find one. What I want is to have a server that can receive files from multiple sockets at the same time. When a server accepts new connection socket it wraps that socket with a ClientThread class. Here is the code:
public class Server extends Thread {
private ServerSocket server;
private Vector<ClientThread> clients;
#Override
public void run() {
listen();
}
private void listen() {
new Thread("Listening Thread") {
#Override
public void run() {
while (true) {
try {
Socket socket = server.accept();
ClientThread newClient = new ClientThread(socket);
newClient.start();
clients.addElement(newClient);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}.start();
}
ClientThread is a private class inside the Server class. It's always listening for an Object from ObjectInputStream, but also I want to be able to receive one big file after the object. And that is why I think i should use multithreading. Here is the code:
private class ClientThread extends Thread {
public Socket socket;
private boolean loggedIn;
private ObjectInputStream ois;
private BufferedInputStream bis;
public ClientThread(Socket socket) {
this.socket = socket;
loggedIn = true;
InputStream is = socket.getInputStream();
ois = new ObjectInputStream(is);
bis = new BufferedInputStream(is);
}
#Override
public void run() {
receive();
}
private void receive() {
while (loggedIn) {
try {
// this method blocks i guess
Object object = ois.readObject();
// after the object comes the large file
byte[] bytes = new byte[SOME_SIZE];
int bytesRead;
int totalRead = 0;
// reading the large file into memory
while ((bytesRead = bis.read(bytes, totalRead, bytes.length - totalRead)) > -1) {
totalRead += bytesRead;
}
// rest of the code for handling received bytes.......
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
}
}
}
I'm not sure if receiving data like this is even possible since all these client sockets are sending data to the same port on this server (i guess?). And if clients are sending data at the same time, Server needs to know which data is for which client. Is this already taken care of, or i need entirely different approach here?
I don't know if this is a stupid question, but like I said I'm just starting learning this stuff. Also i couldn't test my program because i don't even have code for the Client yet. Just want to make sure I don't go wrong at the very start. If this is wrong, feel free to post some ideas. :) Thanks!
For a start it's not bad :)
You can improve later on by using a Selector but that's another topic.
Some clarifications though: the ServerSocket listens on a specific port. When a remote client connects to it, a communication channel (i.e. socket) is created. If another client connects, another socket is created. Both sockets are different channels and won't interfere with each other because they are connected to a different remote IP and port.
It all has to do with how TCP headers and IP headers are formed: a TCP data packet is sent with its header containing the source and destination port, on top of IP header containing the source and destination IP. Those are used to discriminate between the different sockets.
Regarding the "broadcast" you want to do (as per your comment in #Rajesh's answer), you have options:
Do it yourself in pure TCP with ServerSocket and Socket like you started
Switch to UDP and use MulticastSocket, which has the advantage of issueing a single send, but you'll have to deal with missing/unordered datagrams in your client code (UDP does not guarantee delivery or ordering, like TCP does)
Check NIO with Selector and SocketChannel
Investigate frameworks like jGroups or Netty which do the I/O stuff for you
As you're learning, I suggest you do that in the above order. Using a framework is nice, but going through coding yourself will teach you a lot more.
This will work functionally. Each thread is reading from a separate socket connected to different client (address + port). They are separate streams, so no issues in reading from that like this.
However it would be much better to use asynchronous sockets.
Few things that can be taken care in the current implementation:
1) As a good practice, close the streams/sockets when transfer is complete.
2) For every new connection, a new thread is created. That will not scale. Even some one can send many requests and bring down your app. Would be better to use a thread pool. "ClientThread" can just implement "Runnable" and when a new connection is received, just submit the new "ClientThread" to thread pool. (In this case, would be better to name it as ClientTask instead of ClientThread)
As mentioned, it would be much more efficient and scalable to use asynchronous socket, but it will take some time master it. With this, you can use just one thread to read all sockets in parallel and depending on load, can use the same thread or a pool of threads to process the data received from all the sockets. Note that, even if use a pool, you will not need separate thread for processing each socket...Just to make best use of multiple CPU Cores, can use multiple threads to process the data.
You may try either java nio (Selector + SocketChannels) or netty library. Netty is much easier to use compared to nio.
I'm trying to develop my own communication library based on non-blocking NIO messages. I've been reading 1000 tutorials and book chapters about it and I think that at the end I have something that works with few simultaneous connections. But I'm having some issues when I have many connections coexisting on the server-side.
I have the typical selector implementation with the 4 private methods: accept, finishConnect, read and write. My problem lies on the first two ones: Accept and finishConnect.
When the client opens a new socket, and an acceptable key wakes the selector up, the following code is executed.
private void accept(SelectionKey key) {
try {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
LOGGER.debug("Socket " + sc.hashCode() + "-" + sc.socket().toString() + " connexion completed");
changeInterest(sc, SelectionKey.OP_READ);
eventManager.addEvent(new ConnectionEstablished(sc));
} catch (Throwable e) {
NIOException ne = new NIOException(NIOException.ErrorType.ACCEPTING_CONNECTION, e);
eventManager.addEvent(new ErrorEvent(null, ne));
}
}
On the client side, I have this implementation for the connect method that will be invoked once the server processes its acceptable key for the socket.
private void finishConnect(SelectionKey key) {
SocketChannel sc = (SocketChannel) key.channel();
try {
if (sc.finishConnect()) {
eventManager.addEvent(new ConnectionEstablished(sc));
LOGGER.debug("Socket " + sc.hashCode() + "-" + sc.socket().toString() + " connection finished");
} else {
LOGGER.debug("REFUSED " + sc + " - " + sc.socket().toString());
refusedConnection(sc, null);
key.cancel();
}
} catch (Exception e) {
refusedConnection(sc, e);
key.cancel();
}
}
The thing is that when I create some connections are accepted, the client executes the finishConnect message (and I can see the socket connection established with the ports used). But I can't find this connection acceptance on the server side, there is no connection completed log message using those ports!!
I suspected that an exception could arise between the ssc.accept() and the log invocation so I added some extra log messages to check which instruction was blowing everything up. The sequence was completed for all the keys that got into the accept method.
How is that possible if I can't even see any Error message on the log ?
EDIT: I made some tests on the number of sockets that are open at a time. When the client starts running, there's just one openSocket on the server: the server socket. After that it has up to 200 simultaneous open sockets, and at the end of the client execution the servers goes back to 1 open socket. I guess that they are never counted
By now, I've made a workaround that monitors the amount of coexisting connections on the node and delays new connections acceptance until that number is reduced to a given threshold. However I would like to understand what's going wrong on.
Thanks for your help.
Because of the backlog queue, it's perfectly in order for a large number of client connections to complete before accept() is executed. So there is no actual problem here to solve.
But are you ever executing the accept() method? This is the bug you need to investigate.
As EJP suggested the problem was on the backlog queue. I was binding the ServerSocketChannel using the bind(SocketAddress local) method.
When a socket request arrives to the JVM it is enqueued to the backlog queue and waits there until the Listener triggers the process of the corresponding key to be accepted. The actual problem lies on the size of this queue, using the bind method, it stores up to 50 connections.
When a peak of connection requests happens, there's an overflow on the queue and some of them are lost. To avoid this happening, the method bind(SocketAddress local, int backlog), allows to change the capacity of the queue and increase it.
On the other side, when working in non-blocking mode, the selector on the client node does not need the connection to be accepted to process a OP_CONNECT key. The reception of the SYN-ACK TCP message will trigger the corresponding key in the selector.
I've been searching for an answer to my problem, but none of the solutions so far have helped me solve it. I'm working on an app that communicates with another device that works as a server. The app sends queries to the server and receives appropriate responses to dynamically create fragments.
In the first implementation the app sent the query and then waited to receive the answer in a single thread. But that solution wasn't satisfactory since the app did not receive any feedback from the server. The server admin said he was receiving the queries, however he hinted that the device was sending the answer back too fast and that the app probably wasn't already listening by the time the answer arrived.
So what I am trying to achieve is create seperate threads: one for listening and one for sending the query. The one that listens would start before we sent anything to the server, to ensure the app does not miss the server response.
Implementing this so far hasn't been succesful. I've tried writing and running seperate Runnable classes and AsyncTasks, but the listener never received an answer and at some points one of the threads didn't even execute. Here is the code for the asynctask listener:
#Override
protected String doInBackground(String... params) {
int bufferLength = 28;
String masterIP = "192.168.1.100";
try {
Log.i("TCPQuery", "Listening for ReActor answers ...");
Socket tcpSocket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(masterIP, 50001);
try {
tcpSocket.connect(socketAddress);
Log.i("TCPQuery", "Is socket connected: " + tcpSocket.isConnected());
} catch (IOException e) {
e.printStackTrace();
}
while(true){
Log.i("TCPQuery", "Listening ...");
try{
Log.i("TCPQuery", "Waiting for ReActor response ...");
byte[] buffer = new byte[bufferLength];
tcpSocket.getInputStream().read(buffer);
Log.i("TCPQuery", "Received message " + Arrays.toString(buffer) + " from ReActor.");
}catch(Exception e){
e.printStackTrace();
Log.e("TCPQuery", "An error occured receiving the message.");
}
}
} catch (Exception e) {
Log.e("TCP", "Error", e);
}
return "";
}
And this is how the tasks are called:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
listener.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
sender.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
}
else {
listener.execute();
sender.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
How exactly would you approach this problem? If this code is not sufficient I would be glad to post more.
This is because Android's AsyncTask is actually only one thread, no matter how many you create, so if you really want 2 threads running at the same time, I suggest you use standard Java concurrent package tools, not AsyncTask. As explained in the documentation:
AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and
FutureTask.
Look this is tcp connection. So you don't need to bother about data lose. This is port to port connection and it never sends end of stream (-1). Perhaps you have to care about read functionality. Because you can not conform all steams are received or not. Tcp read method is a blocking call. If your read buffer size is smaller than available stream size then it block until it can read fully. And you are using android device, perhaps available stream can vary depending upon your device network. So you have 2 options,
1) your buffer size should be dynamic. At first check your available input stream size by using is.available() and create your buf size by this size. If available size is zero then sleep for a certain time to check it is lost its stream availability or not.
2) set your input stream timeout. It really works, because it reads its available stream and wait for the timeout delay, if any stream is not available within the timeout period then it throws timeout exception.
Try to change your code.
I saw plenty of similar questions on SO but hardly any of them have Socket in the picture. So please take time to read the question.
I have server app (using ServerSocket) which listens for requests, and when a client attempts to connect, new thread is created to serve the client (and server is back to listening mode for new requests). Now, I need to respond one client based on what other client sent to server.
Example:
ServerSocket listening for incoming connections.
Client A connects, new thread is created to serve A.
Client B connects, new thread is created to serve B.
A sends message "Hello from A" to the Server.
Send this message as a response to Client B.
I'm new to this whole "inter-thread communication" thing. Obviously, above mentioned situation sounds dead simple, but I'm describing this to get a hint, as I'll be exchanging huge amount data among clients keeping server as intermediate.
Also, what if I want to keep a shared object limited to, say 10, particular Clients? such that, when 11th client connects to the server, I create new shared object, which will be used to exchange data between 11th, 12th, 13th..... upto 20th client. And so on for every single set of 10 clients.
What I tried: (foolish I guess)
I have a public class with that object supposed to be shared as public static, so that I can use it as global without instantiating it, like MyGlobalClass.SharedMsg.
That doesn't work, I was unable to send data received in one thread to the other.
I'm aware that there is an obvious locking problem since if one thread is writing to an object, other can't be accessing it until the first thread is done writing.
So what would be an ideal approach to this problem?
Update
Since the way in which I create threads for serving incoming connection requests, I can't understand how I can share same object among the threads, since using Global object as mentioned above doesn't work.
Following is how I listen for incoming connections and create serving threads dynamically.
// Method of server class
public void startServer()
{
if (!isRunning)
{
try
{
isRunning = true;
while (isRunning)
{
try
{
new ClientHandler(mysocketserver.accept()).start();
}
catch (SocketTimeoutException ex)
{
//nothing to perform here, go back again to listening.
}
catch (SocketException ex)
{
//Not to handle, since I'll stop the server using SocketServer's close() method, and its going to throw SocketException anyway.
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
else
System.out.println("Server Already Started!");
}
And the ClientHandler class.
public class ClientHandler extends Thread
{
private Socket client = null;
private ObjectInputStream in = null;
private ObjectOutputStream out = null;
public ClientHandler(Socket client)
{
super("ClientHandler");
this.client = client;
}
//This run() is common for every Client that connects, and that's where the problem is.
public void run()
{
try
{
in = new ObjectInputStream(client.getInputStream());
out = new ObjectOutputStream(client.getOutputStream());
//Message received from this thread.
String msg = in.readObject().toString();
System.out.println("Client # "+ client.getInetAddress().getHostAddress() +" Says : "+msg);
//Response to this client.
out.writeObject("Message Received");
out.close();
in.close();
client.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
I believe that the way I'm creating dynamic threads to serve each client that connects, sharing the same data source is not possible using Global object, since the body of run() above is exactly the same for every client that connects, hence this same method is both consumer and producer. What fixes should I make such that I could create dynamic threads for each connection and still share the same object.
You probably want a queue for communication between each client. Each Queue will be the 'pipeline' for data pushed from one client to the other.
You would use it like so (pseudo code):
Thread 1:
Receive request from Client A, with message for Client B
Put message on back of concurrent Queue A2B
Respond to Client A.
Thread 2:
Receive request from Client B.
Pop message from front of Queue A2B
Respond to Client B with message.
You might also want it generic, so you have a AllToB Queue that many clients (and thus many threads) can write to.
Classes of note: ConcurrentLinkedQueue, ArrayBlockingQueue.
If you want to limit the number of messages, then ArrayBlockingQueue with its capacity constructor allows you to do this. If you don't need the blocking functionality, you can use the methods offer and poll rather than put and take.
I wouldn't worry about sharing the queues, it makes the problem significantly more complicated. Only do this if you know there is a memory usage problem you need to address.
EDIT: Based on your update:
If you need to share a single instance between all dynamically created instances you can either:
Make a static instance.
Pass it into the constructor.
Example of 1:
public class ClientHandler extends Thread
{
public static final Map<ClientHandler, BlockingQueue<String>> messageQueues
= new ConcurrentHashMap<>();
<snip>
public ClientHandler(Socket client)
{
super("ClientHandler");
this.client = client;
// Note: Bad practice to reference 'this' in a constructor.
// This can throw an error based on what the put method does.
// As such, if you are to do this, put it at the end of the method.
messageQueues.put(this, new ArrayBlockingQueue<>());
}
// You can now access this in the run() method like so:
// Get messages for the current client.
// messageQueues.get(this).poll();
// Send messages to the thread for another client.
// messageQueues.get(someClient).offer(message);
A couple of notes:
The messageQueues object should really contain some sort of identifier for the client rather than an object reference that is short lived.
A more testable design would pass the messageQueues object into the constructor to allow mocking.
I would probably recommend using a wrapper class for the map, so you can just call offer with 2 parameters rather than having to worry about the map semantics.
I'm accepting a connection from a client and then passing that connected socket off to another object, however, that socket needs to be non-blocking. I'm trying to use getChannel().configureBlocking(false) but that does not seem to be working. It needs to be non-blocking because this the method below is called every 100ms. Is there some other way that I should be making this non-blocking? Thanks for any help!
public void checkForClients() {
DataOutputStream out;
DataInputStream in;
Socket connection;
InetAddress tempIP;
String IP;
try {
connection = serverSocket.accept();
connection.getChannel().configureBlocking(false);
System.err.println("after connection made");
in = new DataInputStream(connection.getInputStream());
out = new DataOutputStream(connection.getOutputStream());
tempIP = connection.getInetAddress();
IP = tempIP.toString();
System.err.println("after ip string");
// create a new user ex nihilo
connectedUsers.add(new ConnectedUser(IP, null, connection, in, out));
System.err.println("after add user");
} catch (SocketTimeoutException e) {
System.err.println("accept timeout - continuing execution");
} catch (IOException e) {
System.err.println("socket accept failed");
}
}
Two things:
Why aren't you using a ServerSocket if you're listening for connections?
If you want to accept multiple clients you want to use a loop.
The basic structure of a multi-client server is:
while (true) {
// accept connections
// spawn thread to deal with that connection
}
If the issue is blocking on the accept() call, well that's what accept() does: it blocks waiting for a connection. If that's an issue I suggest you have a separate thread to accept connections.
See Writing the Server Side of a Socket.
I would expect your code to block on the accept call, never getting to the configureBlocking call.
I typically spin off a separate thread for each socket connection, and let it block until a connection is actually made/accepted This allows the main thread to continue unblocked while it is waiting for client connections.
If you're looking for non-blocking sokets, my suggestion is to use Selectors and ServerSocketChannels with the NIO package.
http://java.sun.com/j2se/1.4.2/docs/guide/nio/
If the typical blocking socket doesn't give you the availability you need (a connection every 100ms does seem tight). You should look at a non-blocking socket. Here is a tutorial. You can also look at Apache MINA to make this easier.
One approach is to use an I/O loop (event loop) in a single threaded environment. Take a look at Deft web server for inspiration. (Especially the start() method in IOLoop)