Block until DataInputStream is available - java

I am making an HTTP server as a project for a class that I am attenting ,for a week now I have stuck trying to find a solution .I have a DataInputStream and I need to wait for the client to send me the http request,there can pass hours before that happens since the connection remains open.This is my code
DataInputStream dis=new DataInputStream(socket.getInputStream());
DataOutputStream dos =new DataOutputStream(socket.getOutputStream());
while(!socket.isClosed()){
try{
/**wait until there are new data in to the stream,if the connection is no more alive then close it*/
while(dis.available()==0){
if(alive==false){
socket.close();
break;
}
}
/*at this point the stream has new data ,or the alive attribute has been set to false */
if(!socket.isClosed()){
/*parse the request text */
Request request=new Request(dis,this);
/*generate a response based on the request*/
Response response=new Response(request,this);
/*send the response back to the client*/
response.send(dos);
/*log the details of the communication*/
Logger.log(toString(request,response,socket));
/*if the request is bad formatted or it has its Connection header set to close , close the connection after sending the response*/
if(request.isBadRequest() || !"keep-alive".equalsIgnoreCase(request.getHeader("Connection"))){
close();
}
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
on the while(dis.available()==0) part I am waiting for the stream to have some data,but the problem is that if I have many connections my server starts to get very much cpu time slowing my computer down since it just hangs doing the loop again and again not giving the chance to the cpu to do good scheduling.If the dis.available() was a blocking command then everything would had been perfect.Any workaround?

InputStreams already block in the read methods while no data is available.
You don't need a single one of these available() calls or loops around them.
You should also note that Socket.isClosed() only returns true if you have closed the socket. It doesn't tell whether the peer has closed the connection.

Related

Socket stream not able to flush

I am writing an app for android 4.2, currently debugged on a Samsung s2+.
The app establishes a connection to a server using a Socket, and the server is using a ServerSocket and the establish()-method to get its socket. So far so good. Since I have to make all the networking in android in a new thread, I created a new class extending Thread which communicates with an underlying Activity (for user input) using a BlockingQueue. The threads run method:
public void run() {
Socket s = null;
try {
s = new Socket(info.getIp(), 1337);
} catch (IOException e) {
e.printStackTrace();
}
String code = null;
try {
code = queue.take();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Log.e("DONE", code);
PrintWriter out = null;
try {
out = new PrintWriter(s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
out.write(code);
out.flush();
}
The connection is up and running, and the logged message "DONE"+code is logged. However, nothing is received on the server side until I force close the app. Is an android thread not able to flush data?
EDIT: If close the socket immediately after writing to it, the text arrives without having to force close the app. Why can't I read the text in the server if the socket is still alive?
try add a newline to the string you sent to server , something like :
out.write(code+"\n");
out.flush();
and as EJP said above put the out.write inside the try / catch
A socket connection only provides the ability to send and receive bytes. As soon as the client sends a byte, the server will receive it. Also, as soon as a client is disconnected, the server will know about it - this is about the extend of what you get from sockets.
The concept of a message does not exist at this level. A message is instead defined by whatever lies above the socket, so most protocols use one or more of three different ways to chunk streams of bytes into "messages"
a special byte or sequence of bytes indicates the end of the message (a new line for example, which seems to have been your case :)
each message starts with x bytes which provide the length of the message (so a simple "05aaaaa02bb" stream of bytes might mean that 2 messages were send - "aaaaa" and "bb"
the entire socket connection lasts for a single message (end of message comes when the connection is closed). This is how HTTP 1.0 works for example.

StreamCorruptedException with heavy data over ObjectInputStream

I have a server-client setup over TCP where the client is sending a number of data sets to the server. The reading/writing uses ObjectInput/OutputStream. I don't have any problems under normal conditions, but when the data flow gets heavy, I get a StreamCorruptedException: invalid type code. The invalid code is different every time. I open the socket once and call a synchronized method to send data from multiple threads.
Client:
socket = new Socket("localhost", sockNum);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
public synchronized void sendMsg(Message msg){
try{
out.writeObject(security.signObject(msg, privKey));
out.reset();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Server:
ServerSocket server = new ServerSocket(sockNum);
Socket client = server.accept();
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
while(threadActive){
Object line = in.readObject();
handleObject(line);
}
Update: I added out.reset() after each send, but that didn't help the problem. I've also added sleep statments in my loop to decrease the data rate. This gets rid of the error but is not a real solution.
Edit: So it's been a little while since I originally asked this, but I'm running into the problem again. I tried setting up my system so that after every sent message, the thread waits for an "acknowledge" message in return. If the receiving process has the StreamCorruptedException, it sends back a "resend" rather than an ack. This seems to be causing more problems than solutions. Any other ideas?
It sounds like you are writing to the output stream in a multi threaded way i.e. you are writing to it somewhere other than in your example.
BTW: Are you reset()ing the stream regularly to prevent a memory leak?

How to listen to incoming packets on a port?

I want to listen to incoming packets on port 19132 and print them out as they come, but so far my code doesn't exactly print anything at all. There is a server forwarding the packets through port 19132 to my computer, and the port is open and enabled, but still nothing is printed.
public static void listenToPort(){
try{
ServerSocket serverSocket = new ServerSocket(19132);
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
try{
System.out.println(in.readLine());
}
catch(IOException e){
System.out.println("Connection to server lost!");
System.exit(1);
break;
}
}
}
catch(IOException e){
System.out.println(e.getMessage());
}
}
On the server side there is info being sent, but the client program (this script) doesn't receive anything, what's the problem?
You are reading lines, not 'packets'. If the data being sent to this port doesn't contain newlines, readLine() will block forever, or until the peer closes the connection.
On the other hand when it does read something, or EOS, your code will spin forever printing null, because you aren't checking for readLine() returning null, at which point you must close the socket and exit the loop.
Not to mention, it might be entirely possible that the System.exit doesn't give enough time for the console to flush it's output (i'm not 100% sure if System.exit will or won't cause a flush in System.out and System.err).
Why don't you attach a debugger to your server process and see if it's even getting past the in.readLine()? As one of the other posters mentioned, if you're not sending a newline character, in.readLine() would block until you do.
Secondly, you shouldn't really use System.exit. It's bad form in most cases and leads to people wondering why the hell an app would just randomly quit. If you want to exit an app, you should allow the code to return back to the main() method, and from there you can do a System.exit if necessary.

SeverSocket stops accepting

I'm working on a game with a event based structure with the main game logic hosted on a server; currently it's a very small featureset that only allows to host one game between exactly two participants. I've read on various questions about ServerSocket and none of them answers my question. I already took a look at
ServerSocket accept continues to block
ServerSocket.accept()
Java ServerSocket won't accept new connections until close() is called on the accepted socket
ServerSocket accept() method
In my project I utilize ObjectInputStream and ObjectOutputStream. Everything works as expected (receiving / sending both on server and client side), but after both sockets are registered, the accept method of the ServerSocket instance continues to block forever, even if the same code is invoked before. Perhaps it's an issue that appears after communicating over a socket once?
My server log shows the following:
waiting for accept
accepting first socket
sending an event to socket1 for informing about waiting for the opponent
waiting for accept
accept second socket
sending responses to both sockets
waiting for accept (and blocking forever)
When the log says response events where sent, they were properly received and processed at the client side. The client side debug outputs show that the next event is definitely sent. Maybe it's about not closing the client sockets (mentioned in the third linked question)? Anyway I can't close the client sockets because further communication would be impossible.
Client side code
public void send(Event e) {
try {
ObjectOutputStream out = new ObjectOutputStream(
socket.getOutputStream());
out.writeObject(e);
out.flush();
log.debug("sending event... "+e);
}
catch(IOException ioe) {
log.fatal("constructing oos failed", ioe);
}
}
Server side code
#Override
public void run() {
running = true;
while(running) {
try {
Socket s = socket.accept();
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
Event event = (Event) ois.readObject();
try {
Event[] response = controller.consume(event);
ObjectOutputStream oos = new ObjectOutputStream(sockets[0].getOutputStream());
oos.writeObject(response[0]);
oos.flush();
ObjectOutputStream oos2 = new ObjectOutputStream(sockets[1].getOutputStream());
oos2.writeObject(response[1]);
oos2.flush();
}
catch(...) {
// multiple catch clauses for different exceptions
// all just logging (nothing passes silently!)
}
}
}
For shortening, the method for assigning the two sockets to the Socket[] array was left out, but since there are no exceptions, keeping the socket works. Do you have any idea what could cause the described behavior? Thank you in advance.
The accept method only accepts new connections. Since you only have two clients attempting to connect to your server, it will hang indefinitely on your third invocation of accept.
Side note: You don't need to continuously create new ObjectInputStreams and ObjectOutputStreams. You can just create one of each for each Socket and keep references to them for reuse.

Socket not closing when calling socket.close()

I found the same problem in this post, but i think it wasn't solved.
i'm going to be brief, this is my code:
try {
Socket pacConx = new Socket(ip, Integer.parseInt(port));
DataInputStream dataIn = new DataInputStream(pacConx.getInputStream());
DataOutputStream dataOut = new DataOutputStream(pacConx.getOutputStream());
while(){...}
} catch (IOException e) {
logger.fatal("error", e);
}finally{
if (dataIn != null) {
dataIn.close();
}
if (dataOut != null) {
dataOut.close();
}
if (pacConx != null) {
pacConx.close();
}
}
First, i connect to the server using the code above, and it succeed.
But, when i try to REconnect to the same server and port after a while, i cannot reconnect.
Apparently the first socket is still "alive" in the serverSide.
is the a solution to my peoblem ?
Is there a way that i can close the other "alive" socket ?
Try
...
dataOut.flush();
dataOut.close();
...
Paste error message or/and full stack trace.
You need to initiate an orderly disconnect. After calling flush on the streams, and before calling close on the socket, add this:
pacConx.shutdownInput();
pacConx.shutdownOutput();
That tells the remote end you're finished and allows it to dismantle the port without waiting to make sure there isn't data still in transit.
For about 2-4 minutes after you close the socket it will hang in "CLOSE_WAIT" state on the server. This is a normal part of the TCP/IP protocol to handle delayed packets still wandering around in the network.
This should be handled by your server code. Is it unbinding its listen socket while handling a request and trying to re-establish it after the close? If so, it should either leave the listen up during processing or re-establish it with a SO_REUSEADDR option.

Categories