I'm trying to communicate through sockets using TCP. The data that needs to be sent is a drawing, whilst it is being drawn. So the option would be to send all the points, or only shapes (series of points).
Since it would be nice to have it being drawn instantly, sending points seems better. It's only for local use, so a lot of data shouldn't be an issue. Now the issue I'm having is understanding how exactly the socket works. Currently my code is as follows:
while(true){
try {
Thread.sleep(10);
}
catch (InterruptedException e) {}
switch(connectionStatus){
case CONNECTED:
if(isHost){
try {
oos.writeObject(myObject);
} catch (IOException e) {
e.printStackTrace();
}
}else{
try {
myObject = (myObjectType) ois.readObject();
mainFrame.repaint();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
break;
}
}
But needless to say, this seems rather inefficiƫnt as it's running constantly. Is there a way to only write to the ObjectOutputStream (oos) when new data is there? I guess to read you have to poll though. Does reading also clear the ObjectOutputStream?
Edit
To be clear: I want to send multiple Point-objects through a socket. So every time a Point gets added to eg the server, it should send this point to the client.
Now, what do I need to put inside the oos.writeObject()? The single Point, or a List of Points? And how are they retrieved from the ois.readObject()?
I'm a bit confused, because the writing to the ObjectOutputStream could be fast or slow. Se reading the ObjectInputStream - the way I see it - would or cause a big delay (if it reads a value every ~15ms and points get added faster than that) or cause lots of lag.
Is there a way to only write to the ObjectOutputStream (oos) when new data is there?
Yes. Whenever the user draws something, push data down the ObjectInputStream.
I guess to read you have to poll though.
That is incorrect. Typically, reading from an open stream is a blocking operation: if you attempt to read something and there's nothing there, the read method will simply block until new data is available.
For writing, you need to employ threading and synchronization technique in order to write only when data is available. One thread to notify that new data has become available, another to wait and be notified and continues execution when it is told that data has come;
Reading doesn't clear ObjectOutputStream. In fact, you can use two threads to handle input and output streams concurrently.
Reading an object is an synchronous operation, meaning your thread waits until the object is ready.
I wrote a library (which you can find on maven) that will take away some the complexity of implementing threading and synchronization yourself:
https://github.com/xtrinch/socket-live
Consists of three main components (which later result into three running threads):
SocketConnection.java: main thread, run by the user of the library, which makes sure the connection is always open
SocketRead.java: read thread which continuously attempts to read incoming messages if any
SocketWrite.java: write thread which writes any messages in write queue to socket
You also have the option to disable the read thread, if you don't need it.
Library will make sure the connection stays open at all times, reconnect upon being closed, and it's been battle tested :)
Related
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?
I have made a client-server application which can connect over the internet. I have hard coded in my client the server's IP which is fixed.
My question is that I want a way that will not take a lot of processing and memory.
I want my client to check if internet is available and then try to connect to the server if its up and running. If not then to wait and try again.
Keeping in mind that the app is supposed to always run on your computer 24/7 and connect when possible just like skype does, in the sense that its always on and when you have the internet available and server reachable , it connects.
My client's code that connects to the server:
private void connectToServer() throws Exception {
showMessage("Attempting Connection... \n");
try{
connection = new Socket(InetAddress.getByName(serverIP), 6789);
showMessage("Ok dude you are Connected to:" + connection.getInetAddress().getHostName());}
catch(IOException e){
int x = 0;
while (true){
try {
showMessage("Sorry Your IP was not found, \nAutomatic detection:");
showMessage("Now trying again");
connection = new Socket(InetAddress.getByName(serverIP),6789);
break;
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
showMessage("\nConnection not established, trying again\n");
}
/*x++;
if(x>10) break;*/
}
//throw new Exception();
}
}
This does work but takes a lot of processing and memory !
I know that by adding thread.sleep(5000), I am going to add them eventually etc...
But this doesn't solve the memory problem. My program would be running for a long time and this doesn't stop the inevitable.
Is there a better way?
THANKS
P.S : showMessage() is just my function that displays the output on my GUI
The way I checked memory was using Window's Task Manager !
(the memory increases drastically)
As you've noted in your question already, you should add a call to Thread.sleep() within the loop. As your code stands right now, it runs a tight endless loop that will be very taxing on the CPU.
As for memory usage, are you sure that the memory used is actually growing? The JVM may be allocating a large chunk of memory off the bat even for a simple program -- you should check to make sure that the usage is actually growing. If it is indeed a problem, it may just be because you're making a new Socket in each cycle of a tight loop, in which case adding the sleep() call would solve the issue by allowing the GC to take care of old Socket objects in time.
By the way, have you noticed that your code performs the exact same check again if the first one fails? Why not start the loop immediately and just perform the check once within the loop? This would allow you to significantly reduce your code's complexity. Look into the software guideline often referred to as "Don't Repeat Yourself" to learn more.
It seems you are having two problems
How to check internet is available - please refer
Preferred Java way to ping an HTTP URL for availability
Detect internet Connection using Java
How to check if internet connection is present in java?
Memory leak
You need to clean up the socket object if the connection fails.
I used the Java Knock Knock tutorial for creating a client-server connection but I cant figure out how to check if the socket is still open.
Simplified code:
try {
while ((clientMessage = inFromClient.readLine()) != null) {
//do stuff
} catch (IOException e) {
//client disconnected
e.printStackTrace();
}
}
This works great, however I noticed that when the client is Linux based the exception isn't thrown if client gets forcefully closed. I tried some suggestions posted by others but can't get any working. I tried to implement a loop that checks how long its been since last message was received but it didn't work, the loop had to be inside the loop in the above code, and the loop is only executed when a new message is received from the client. I'm very confused but I don't understand how to implement any methods of checking.
If I put the method to check for inactivity outside the above loop then it's never called because the socket loop is indefinite (unless socket is closed).
Just set a read timeout with Socket.setSoTimeout(). Set it to higher than the expected request interval, say double that. If it expires, you will get a SocketTimeoutException: close the socket.
Contrary to some of the comments, isConnected(), isBound(), isClosed(), etc. are no use for this. They tell you whether you connected, bound, closed, etc. the Socket. Not about the state of the connection.
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.
Im trying to run a thread that goes to a socket, grabs the input stream, and reads it. Im creating hundreds of these threads and have set the timeout for reading and yet the thread still stays at the read() line.
public void readPack() {
socket.setSoTimeout(4*1000);
if (socket.isConnected()) {
buffer parse = new buffer();
parse.addByte((byte) skt.getInputStream().read());
parseIncoming(parse);
}
} catch (Exception e) {}
}
Strange code. You create a buffer, read one byte into it, then parse that byte, then repeat the whole process. One byte surely doesn't take much parsing. You are never checking for -1 from the read so this loop will spin endlessly when the peer disconnects. And finally Socket.isConnected() isn't a useful test, and specifically it doesn't detect the peer disconnecting.
Call skt.available(), and then call read that many times, or use skt.read(byte[]). Other wise skt.read() will block. The timeout your setting is to connect to the socket, and not a read timeout.