/* JAVA CLIENT: ------------ COMMAND_LENGTH -------> :SERVER */
/* JAVA CLIENT: -------------- COMMAND ------------> :SERVER */
/* JAVA CLIENT: <-------------- RESULTS ------------ :SERVER */
- /* JAVA CLIENT: <---------- CLOSE CONNECTION ------- :SERVER */
+ /* JAVA CLIENT: ----------- CLOSE CONNECTION ------> :SERVER */
/* */
/****************************************************************************************/
/*3. RESULTS*/
- pre_fork_system(socket, command);
-
+ if (pre_fork_system(socket, command) < 0)
+ goto err;
- /*4. CLOSE CONNECTION AND FINISH*/
+ /*4. WAIT FOR CLIENT TO CLOSE CONNECTION AND FINISH*/
+ // We may avoid the TIME_WAIT state in the server side if we always wait for the client to close the connection.
+ // Never use SO_LINGER!!! The client should be able to know when there are no more data. The protocol
+ // (application level) should notify the client when the server ended up sending data and in this
+ // way the client is able to close the connection.
+ // See:
+ // http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable
+ // http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
+ // http://stackoverflow.com/questions/3757289/tcp-option-so-linger-zero-when-its-required
+ bzero(buffer, sizeof(buffer));
+ // TODO: I just want to wait until the socket is closed (or there is a timeout).
+ // Should I use another method for that instead of this one? :/ This code does not look clear to me... There must be something better...
+ if (receive_from_socket (socket, buffer, sizeof(uint32_t), timeout, utimeout) < 0)
+ goto err;
err:
free(command);
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
-import java.io.EOFException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
private String streamStderr;
//Error by default.
private int results = -1;
+ int type;
+ int length;
/**
/* JAVA CLIENT: ------------ COMMAND_LENGTH -------> :SERVER */
/* JAVA CLIENT: -------------- COMMAND ------------> :SERVER */
/* JAVA CLIENT: <-------------- RESULTS ------------ :SERVER */
- /* JAVA CLIENT: <---------- CLOSE CONNECTION ------- :SERVER */
+ /* JAVA CLIENT: ----------- CLOSE CONNECTION ------> :SERVER */
/* */
/******************************************************************************************/
//sends response to Java client and here we know the character set encoding is the defined for TCPForkDaemon protocol
//(for example UTF-8) In this way we do not need to know about the remote encoding and everything could run automatically.
receiveData = new DataInputStream(socket.getInputStream());
- while (true) {
- int type = receiveData.readInt();
- int length = receiveData.readInt();
+ this.type = receiveData.readInt();
+ this.length = receiveData.readInt();
+ while (this.type != 3) {
+
switch (type) {
case 0:
//STDIN not implemented
receiveData.readFully(dataStderr, 0, length);
stderr.write(dataStderr, 0, length);
break;
- case 3:
- //RESULTS
- results = length;
- break;
default:
throw new IOException("Unrecognized type.");
}
+
+ this.type = receiveData.readInt();
+ this.length = receiveData.readInt();
}
- } catch (EOFException e) {
- // 4. SERVER CLOSED CONNECTION
- //TODO: Java NIO with select, and stop using this crappy code.
}
finally {
if (lengthAndCommand != null) {
socket.close();
}
- //The remote charset.
- //TODO: my own protocol as above specified.
- this.streamStderr = new String(stderr.toByteArray(), "UTF-8");
- this.streamStdout = new String(stdout.toByteArray(), "UTF-8");
}
-
+
+ //RESULTS
+ //The remote charset.
+ //TODO: my own protocol as above specified.
+ this.streamStderr = new String(stderr.toByteArray(), "UTF-8");
+ this.streamStdout = new String(stdout.toByteArray(), "UTF-8");
+
//If everything went all right we should be able to retrieve the return
//status of the remotely executed command.
+ this.results = this.length;
return this.results;
}