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.
Related
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'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 :)
I have a very simple question.
Based on Java I/O scheme, whenever a thread is waiting for some data, so it will be blocked? is it true? something like this.
byte[] _buff=new byte[1024];
int _r=_in.read(_buff);//it blocks until some data is available
and the just possible way to give up reading is closing the stream by another thread, is it right? something like this.
void run(){
_in.close();
}
so if I am right with above scenarios, so why this is impossible just interrupt a thread which is reading from System.in by closing the stream. I run a thread that just waits for 5 seconds then wants to interrupt/give up rest of the reading from the stream.
void _read_data(){
System.out.print("enter y to save the workspace ");
new Thread(_cancel_thread).start();
int _r=System.in.read();//blocks
}
///////////
void run(){
try{
Thread.sleep(5000);
System.in.close();//doesn't work.
}catch(Exception _ex){}
}
Questions:
1.How to close the stream?! why the closing stream thread cannot close the stream?!
2.Once the stream got closed, how to open it again?!
For the first question, I think this is because maybe(I don't know, not sure) the stream is kinda locked by lower-level, so while it's locked, another thread is just waiting to acquire the lock and close it.
and for second one, I really don't know is there any class(stream) which works with keyboard stream or not, but why do you really want to close it? just keep the stream somewhere (like in=System.in), then redirect the standard stream to another stream by calling System.setIn(newStream), then whenever you want to give keyboard stream back, reset the stream with the reference.
Closing the default system input stream is not good idea, I suggest you utilize either JConsol or jNativeHook, these guys do not block, instead they listen for events.
I have this weird problem with my (multithreaded) server when I get more than 500 players connected simultaneously, the PrinterWriter take more than 100 seconds or more (2 minutes) to finish flush() or print() sometimes.
Here is the code:
public static void send(Player p, String packet)
{
PrintWriter out = p.get_out();
if(out != null && !packet.equals("") && !packet.equals(""+(char)0x00))
{
packet = Crypter.toUtf(packet);
out.print((packet)+(char)0x00);
out.flush();
}
}
the printWriter is something like this:
_in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
_out = new PrintWriter(_socket.getOutputStream());
If I add the keyword synchronized to the send() method, the whole server starts to lag every 2 seconds, if I don't then some random player starts to lag for no reason.
Anyone have any idea ? Where is this coming from? What should I do?
The print writer is wrapped around a socket's output stream, so I'm going to guess and say that the socket's output buffer is full, and so the write/flush call will block until the buffer has enough room to accommodate the message being sent.
The socket send buffer may become full if data is being written to it faster than it can be transmitted to the client (or faster than the client can receive it).
Edit:
P.S. If you're having scalability problems, it may be due to using java.io (which requires one thread per socket) instead of java.nio (in which case a single thread can detect and perform operations on those sockets which have pending data). nio is intended to support applications which must scale to a large number of connections, but the programming model is more difficult.
The reason is that your send() method is static, so all threads that write to any socket are being syncrhonized on the containing class object. Make it non-static, then only threads that are writing to the same socket will be synchronized.
My client/server application currently keeps opening and closing new connections every time it wants to send/receive data. I'm trying to change it so it will have one persistent connection.
The problem I'm having is the socket's DataInputStream on the server keeps throwing EOFException's when I just want it to block until it receives the next batch of data.
I thought about just simply writing the server like this...
while socket is open {
while at socket's DataInputStream's EOF {
wait a second
}
//If we're here, then we have some data
do stuff
}
... but this is extremely ugly and not the proper way to block until some data is received.
Is there a cleaner way to tell the socket to block until there's some data to read? I've tried read() and readFully(), but neither work.
If you are getting EOFException, it means the connection is gone. You cannot wait on a connection that's closed. Keep working on your client code so that it doesn't close the connection. On the server side, any of the read methods will block until data is available without further effort from you.