I'm new to working with Socket and have perhaps painted myself into a corner with a spurious design. I think I'd like to find a way to purge or flush the contents of a line decorating a Socket's InputStream. But maybe I've set things up incorrectly?
The Socket is tasked with repeatedly running the following cycle, on demand, on a background thread. A Runnable is instantiated that does the following tasks, then completes:
Send a message to server
Listen for an "ACK"
Wait for response from server
Read and "log" response
Send "ACK"
The runnable holds a class variable that is responsible for reading messages from the ServerSocket. inLine is instantiated in a separate method which is used to establish the connection.
inLine = new BufferedReader(new InputStreamReader(socket.getInputStream()));
My issue is that I am trying to figure out how to handle a test case scenario where the SocketServer sends an "extraneous" message during the interval when the client is dormant. On the next iteration of the cycle, this "extra" message is in the cue ahead of the expected "ACK" in step 2.
I was thinking I would remove any pending messages from the inLine variable prior to launching the runnable. But I don't see any means to do this. There are no flush or clear methods on BufferedReader or InputStreamReader. Nor are there any methods that I can find which allow one to inspect if there are any messages in the queue, along the lines of an iterator's hasNext() method.
Is there something I am missing?
Should I just declare and instantiate the inLine anew with each cycle? I was hesitating to do this because I don't know how expensive it is to continually repeat this operation. (As I said, I'm new to working with Socket-based communications.)
Would something like the following at the top of the cycle be considered ugly, or reasonable?
// clear out any messages sent during dormant time
socket.setSoTimeout(10); // arbitrary, very short timeout
while (true) {
try {
in.readLine();
} catch (SocketTimeoutException ex) {
break;
}
}
EDIT: There are wonderful folks at StackOverflow who I know are doing their best to keep questions in conformance with site standards. If you have a suggestion to help me improve the question, it would be appreciated. Should a question like this perhaps be better posted at "Code Review" now that I have added a plausible routine for clearing the input line?
Related
Situation
I've been creating a program to exchange messages between two computers in the LAN. One computer identifies itself as the server while the other is a client. Upon startup, the user has to enter the Host and the Port of another computer, should he wish to connect as a client to that machine.
The setup of how it works is very basic: You type your message, hit enter and it shows up on your own screen. After that your conversation partner has to click a button to retrieve the latest messages and it should show up on his screen. This goes on untill someone leaves.
Problem
The program launches correctly and asks for the connection settings. After that I initiate the connection on both computers and things seem to go fine (after the connection is established, a label shows you what your status, e.g. Client or Server, is (1)). Things continue looking fine when I enter a message and send it, the output gets written to the sender's screen and no unexpected behaviour occurs.
When I want to retrieve the messages on the other computer, the program completely freezes. No objects in the GUI are clickable and no output is shown.
Code
Assuming the connection is correctly established (see (1)), I will outline the process of sending a message below while leaving out the non-essential parts.
GuiApplication.java
private void sendMessage() {
connection.sendMessage(message);
showMessage(message);
}
Connection.java
public void sendMessage(String message) {
if (isClient()) {
client.sendMessage(message);
} else if (isServer()) {
server.sendMessage(message);
}
}
Client.java
public void sendMessage(String message) {
outbound = new PrintWriter(socket.getOutputStream(), true); // Defined outside this method
outbound.println(message);
}
The process of sending a message is pretty straightforward, but I wanted to include it just in case I've overlooked something.
What follows is the code I've created to retrieve the new messages. The concept is simple: I check if there are any new messages and if there are, I retrieve them.
GuiApplication.java
if (connection.hasNewMessage()) {
message = connection.retrieveMessage();
}
showMessage(message);
The first part (connection.hasNewMessage()) will check whether or not the program is either running the client or the server and call the appropriate retrieveMessage().
Client.java
public String retrieveMessage() throws IOException {
inbound = socket.getInputStream(); // Defined outside this method
return IOUtils.toString(inbound, "UTF-8");
}
At first I've tried this with a BufferedReader using an InputStreamReader and calling the readLine() method, but decided to try out the commons.io method once I noticed it didn't work (the same problem as I am currently facing).
Question
It's been made pretty clear by now: why does my program hang the moment I click a button which retrieves new messages?
External
I'm not sure if it's frowned upon, but here's the github repository in case you wanted a better overview, although I believe the necessary code snippers are there.
I did look at your code, and as I suspected, your problem has absolutely nothing to do with the code you've posted. Your GUI completely ignores Swing threading rules, and calls long-running tasks on the main Swing event thread known as the Event Dispatch Thread or EDT. Since this thread is responsible for all Swing drawing and user interaction, your GUI is prevented from doing this and becomes completely frozen.
Please read Concurrency in Swing for the details on this.
And next time, please post an sscce so we don't have to dive into a huge amount of your source code! The key to the SSCCE is to eliminate all code not essential to your problem at hand. This is not easy to do and will require a lot of work from you to create, so that it has enough code to run, but not too much as to drown us in code, but then you are asking volunteers to help you on their free time, so it's not asking too much.
Best of luck!
Without reading all your explanations and all code attachments I can assume that you are reading from or writing to stream into UI thread (e.g. call IO operation from Action or ActionListener directly and you are blocked on read/write.
Please examine your code. I believe you will find point where you call to in.read() or out.write(). Add print just before and just after the line. You will see that you never exit read or write.
This is because the other side does not perform opposite operation. So, you have to:
decouple UI from IO. IO must be done in separate thread.
check why other side blocks your flow.
I am building a server in java that communicates with several clients at the same time, the initial approach we had is the the server listens to connections from the clients, once a connection is received and a socket is created, a new thread is spawned to handle the communication with each client, that is read the request with an ObjectInputStream, do the desired operation (fetch data from the DB, update it, etc.), and send back a response to the client (if needed). While the server itself goes back to listen to more connections.
This works fine for the time being, however this approach is not really scalable, it works great for a small amount of clients connected at the same time, however since every client spawns another thread, what will happen when there are a too many clients connected at once?
So my next idea was to maintain a list of sorts that will hold all connected clients (the socket object and some extra info), use a ThreadPool for to iterate through them and read anything they sent, if a message was received then put it in a queue for execution by another ThreadPool of worker threads, and once the worker has finished with its task if a response is required then send it.
The 2 latter steps are pretty trivial to implement, the problem is that with the original thread per client implementation, I use ObjectInputStream.readObject() to read the message, and this method blocks until there is something to read, which is fine for this approach, but I can't use the same thing for the new approach, since if I block on every socket, I will never get to the ones that are further down the list.
So I need a way to check if I have anything to read before I call readObject(), so far I tried the following solutions:
Solution 1:
use ObjectInputStream.available() to check if there is anything available to read, this approach failed since this method seems to always return 0, regardless of whether there is an object in the stream or not. So this does not help at all.
Solution 2:
Use PushbackInputStream to check for the existence of the first unread byte in the stream, if it exists then push it back and read the object using the ObjectInputStream, and if it doesn't move on:
boolean available;
int b = pushbackinput.read();
if (b==-1)
available = false;
else
{
pushbackinput.unread(b);
available = true;
}
if (available)
{
Object message= objectinput.readObject();
// continue with what you need to do with that object
}
This turned out to be useless too, since read() blocks also if there is no input to read. It seems to only return the -1 option if the stream was closed. If the stream is still open but empty it just blocks, so this is no different than simply using ObjectInputStream.readObject();
Can anyone suggest an approach that will actually work?
This is a good question, and you've done some homework.... but it involves going through some history to get things right. Note, your issue is actually more to do with the socket-level communication rather than the ObjectInputStream:
The easiest way to do things in the past was to have a separate thread per socket. This was scalable to a point but threads were expensive and slow to create.
In response, for large systems, people created thread pools and would service the sockets on threads when there was work to do. This was complicated.
The Java language was then changed with the java.nio package which introduced the Selector together with non-blocking IO. This created a reliable (although sometimes confusing) way to service multiple sockets with fewer threads. In your case through, it would not help fully/much because you want to know when a full Object is ready to be read, not when there's just 'some' object.
In the interim the 'landscape' changed, and Java is now able to more efficiently create and manage threads. 'Current' thinking is that it is better/faster and easier to allocate a single thread per socket again.... see Java thread per connection model vs NIO
In your case, I would suggest that you stick with the thread-per-socket model, and you'll be fine. Java can scale and handle more threads than sockets, so you'll be fine.
I'm the main developer of an online game.
Players use a specific client software that connects to the game server with TCP/IP (TCP, not UDP)
At the moment, the architecture of the server is a classic multithreaded server with one thread per connection.
But in peak hours, when there are often 300 or 400 connected people, the server is getting more and more laggy.
I was wondering, if by switching to a java.nio.* asynchronous I/O model with few threads managing many connections, if the performances would be better.
Finding example codes on the web that cover the basics of such a server architecture is very easy. However, after hours of googling, I didn't find the answers to some more advanced questions:
1 - The protocol is text-based, not binary-based. The clients and the server exchanges lines of text encoded in UTF-8. A single line of text represents a single command, each lines are properly terminated by \n or \r\n.
For the classic multithreaded server, I have that kind of code :
public Connection (Socket sock) {
this.in = new BufferedReader( new InputStreamReader( sock.getInputStream(), "UTF-8" ));
this.out = new BufferedWriter( new OutputStreamWriter(sock.getOutputStream(), "UTF-8"));
new Thread(this) .start();
}
And then in run, data are read line by line with readLine.
In the doc, I found an utilitiy class Channels that can create a Reader out of a SocketChannel. But it is said that the produced Reader wont work if the Channel is in non-blocking mode, what contradicts the fact that non-blocking mode is mandatory to use the highly performant channel selection API I'm willing to use. So, I suspect that it isn't the right solution for what I would like to do.
The first question is therefore the following: if I can't use that, how to efficiently and properly take care of breaking lines and converting native java strings from/to UTF-8 encoded data in the nio API, with buffers and channels?
Do I have to play with get/put or inside the wrapped byte array by hand? How to go from ByteBuffer to strings encoded in UTF-8 ? I admit to don't understand very well how to use classes in the charset package and how it works to do that.
2 - In the asynchronous/non-blocking I/O world, what about the handling of consecutive read/write that have by nature to be executed sequencially one after the other?
For example, the login procedure, which is typicly challenge-response-based: the server sends a question (a particular computation), the client sends the response, and then the server checks the response given by the client.
The answer is, I think, certainly not to make a single task to send to worker threads for the whole login process, as it is quite long, with the risk to freeze worker threads for too much time (Imagine that scenario: 10 pool threads, 10 players try to connect at the same time; tasks related to players already online are delayed until one thread is again ready).
3 - What happens if two different threads simultaneously call Channel.write(ByteBuffer) on the same Channel?
Do the client might receive mixed up lines ? For example if a thread sends "aaaaa" and another sends "bbbbb", could the client receive "aaabbbbbaa", or am I ensured that everyting is sent in a consist order? Am I allowed to modify the buffer used right after the call returned?
Or asked differently, do I need additional synchronization to avoid this sort of situation?
If I need additionnal synchronization, how to know when release locks and so on, upon write finishes?
I'm afraid that the answer isn't as simple as registering for OP_WRITE in the selector. By trying that, I noticed that I get the write-ready event all the time and always for all clients, exiting Selector.select early mostly for nothing, since there are only 3 or 4 messages to send pers second per client, while the selection loop is performed hundreds of times per second. So, potentially, active wait in perspective, what is very bad.
4 - Can multiple threads call Selector.select on the same selector simultaneously without any concurrency problems such as missing an event, scheduling it twice, etc?
5 - In fact, is nio as good as it is said to be ? Would it be interesting to stay to classic multithreaded model, but unstead of creating a thread per connection, use fewer threads and loop over the connections to look for data availability using InputStream.isAvailable ? Is that idea stupid and/or inefficient?
1) Yes. I think that you need to write your own nonblocking readLine method. Note also that a nonblocking read may be signaled when there are several lines in the buffer, or when there is an incomplete line:
Example: (first read)
USER foo
PASS
(second read)
bar
You will need to store (see 2) the data that was not consumed, until enough information is ready to process it.
//channel was select for OP_READ
read data from channel
prepend data from previous read
split complete lines
save incomplete line
execute commands
2) You will need to keep the state of each client.
Map<SocketChannel,State> clients = new HashMap<SocketChannel,State>();
when a channel is connected, put a fresh state into the map
clients.put(channel,new State());
Or store the current state as the attached object of the SelectionKey.
Then, when executing each command, update the state. You may write it as a monolithic method, or do something more fancy such as polymorphic implementations of State, where each state knows how to deal with some commands (e.g. LoginState expects USER and PASS, then you change the state into a new AuthorizedState).
3) I don't recall using NIO with many asynchronous writers per channel, but the documentation says it is thread safe (I won't elaborate, since I have no proof of this). About OP_WRITE, note that it signals when the write buffer is not full. In other words, as said here: OP_WRITE is almost always ready, i.e. except when the socket send buffer is full, so you will just cause your Selector.select() method to spin mindlessly.
4) Yes. Selector.select() performs a blocking selection operation.
5) I think that the most difficult part is switching from a thread-per-client architecture, to a different design where reads and writes are decoupled from processing. Once you have done that, it is easier to work with channels than working your own way with blocking streams.
I am running 2 threads in my applciation. One to check for incoming packets and one to process and send packets. They both do it on the SAME STREAM.
Example for 1:
while (connection open) {
in.readObject() instanceof ...
}
Example for 2:
while (connection open) {
processPacket(in)
}
I'm pretty sure EOFException is when the threads try and use the stream at the same time. It's not a constant EOF but only like every 1 second I get an EOF the rest works fine. So that's why I suspect that they overlap and try to use the stream at the same time.
If that is the problem, anyone know how do I synchronize them to do it after another while still keeping the current update speed and using two threads?
I need two threads because the check for incoming waits in a line until a packet gets recived and I need the server to constantly send process and check for packets.
How do I fix the EOFException?
If your getting an EOFException, it typically means the other side hung up. You usually get these on the read side.
Here's a similar SO question
Edit 1: The question is really why is the socket closed. It can be for any number of reasons, a programmable timer on the server side checking for no data within X minutes, a firewall closing the connection, a network interruption, etc..
Both threads shouldn't be reading the same Stream.
You should read the objects and put them in a ConcurrentLinkedQueue, then from the second thread you can check the queue for objects ready to process.
EOFException is 'normal'. It happens on one thread too. Your architecture of reading in two threads simultaneously cannot possibly work, but it isn't the cause of this problem. The cause is that the peer closed the connection. This is going to happen. Unless your application protocol contains message counts or a close notify or some other means of predicting EOS, it is going to get EOFExceptions, or readLine() returning null, or read() returning -1, depending which read methods you are calling.
Is there a way to immediately print the message received from the client without using an infinite loop to check whether the input stream is empty or not?
Because I found that using infinite loop consumes a lot of system resources, which makes the program running so slow. And we also have to do the same (infinite loop) on the client side to print the message on the screen in real time.
I'm using Java.
You should be dealing with the input stream in a separate Thread - and let it block waiting for input. It will not use any resources while it blocks. If you're seeing excessive resource usage while doing this sort of thing, you're doing it wrong.
I think you can just put your loop in a different thread and have it sleep a bit (maybe for half a second?) between iterations. It would still be an infinite loop, but it would not consume nearly as many resources.
You don't you change your architecture a little bit to accommodate WebSockets. check out Socket.IO . It is a cross browser WebSockets enabler.
You will have to write controllers (servlets for example in java) that push data to the client. This does not follow the request-response architecture.
You can also architect it so that a "push servlet" triggers a "request" from the client to obtain the "response".
Since your question talks about Java, and if you are interested in WebSockets, check this link out.
If you're using Sockets, which you should be for any networking.
Then you can use the socket's DataInputStream which you can get using socket.getInputStream() (i think that's the right method) and do the following:
public DataInputStream streamIn;
public Socket soc;
// initialize socket, etc...
streamIn = soc.getInputStream();
public String getInput() {
return (String) streamIn.readUTF(); // Do some other casting if this doesn't work
}
streamIn.readUTF() blocks until data is available, meaning you don't have to loop, and threading will let you do other processing while you wait for data.
Look here for more information on DataInputStream and what you can do with it: http://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html
A method that does not require threads would involve subclassing the input stream and adding a notify type method. When called this method would alert any interested objects (i.e. objects that would have to change state due to the additions to the stream) that changes have been made. These interested objects could then respond in anyway that is desired.
Objects writing to the buffer would do their normal writing, and afterward would call the notify() method on the input stream, informing all interested objects of the change.
Edit: This might require subclassing more than a couple of classes and so could involve a lot of code changes. Without knowing more about your design you would have to decide if the implementation is worth the effort.
There are two approaches that avoid busy loops / sleeps.
Use a thread for each client connection, and simply have each thread call read. This blocks the thread until the client sends some data, but that's no problem because it doesn't block the threads handling other clients.
Use Java NIO channel selectors. These allow a thread to wait until one of set of channels (in this case sockets) has data to be read. There is a section of the Oracle Java Tutorials on this.
Of these two approaches, the second one is most efficient in terms of overall resource usage. (The thread-per-client approach uses a lot of memory on thread stacks, and CPU on thread switching overheads.)
Busy loops that repeatedly call (say) InputStream.available() to see if there is any input are horribly inefficient. You can make them less inefficient by slowing down the polling with Thread.sleep(...) calls, but this has the side effect of making the service less responsive. For instance, if you add a 1 second sleep between each set of polls, the effect that each client will see is that the server typically delays 1 second before processing each request. Assuming that those requests are keystrokes and the responses echo them, the net result is a horribly laggy service.