Communication via standard input / output in Java - java

I am trying to send messages between two JVMs: a server starts a second process. The second process is then to send a message to the server which prints the message to the console. The code is as follows:
public class Server
{
public static void main(String[] args)
{
Process client=null;
BufferedReader clientInput=null;
try
{
client=Runtime.getRuntime().exec("java Client");
clientInput=new BufferedReader(new InputStreamReader(client.getInputStream()));
}
catch(IOException e){}
System.out.println("Waiting for the client to connect...");
try
{
String msg=clientInput.readLine();
System.out.println(msg);
}
catch(IOException e){}
client.destroy();
}
}
and
public class Client
{
public static void main(String[] args)
{
BufferedWriter out = new BufferedWriter( new OutputStreamWriter(System.out));
try
{
out.write("Ready\n");
out.flush();
}
catch (Exception e){}
}
}
If I run this, I get as output from the server null. In the end, the communication should be both ways. Any help greatly appreciated.
EDIT: I don't get any errors (just removed the print statements from the catch blocks to save space).

I think you need to add a while loop:
while ((s = in.readLine()) != null && s.length() != 0)
System.out.println(s);
}

You receive null at the end of the stream. The client correctly starts, sends Ready, and the the ends, so the stream ends.
Totally correct behaviour. If the client would end itself (but instead do something else like reading server messages on stdin), the server would never receive a null.
Edit: NEVER EVER (!!!!!) do this:
catch(IOException e){}
At least write:
catch(IOException e){ e.printStackTrace() }
This will show you your error!
In my company, this is one of the elementary rules of code style!

Related

Return value of command fire using socket in Java

My application connects to hardware which is basically a plotter machine which prints data based on the command. I am doing socket connection and firing some commands. In the hardware I can see command has been reached but I am not able to get return value of executed command. Below is the sample code. There is no error but at the execution on this line String cmd = in.readLine(); it got stuck.
Main.Java
public class Test
{
public static void main(String[] args)
{
try
{
PrintTest printTest = new PrintTest();
printTest.print();
}
catch (Throwable e)
{
e.printStackTrace();
}
}
}
Method
public void print() throws IOException
{
Socket socket = null;
try
{
socket = new Socket();
socket.connect(new InetSocketAddress(host, port), 10);
System.out.println("isConnected :- " + socket.isConnected());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
out.write("TC1004,1;");
out.flush();
String cmd = in.readLine();
System.out.println("Recieved: " + cmd);
}
catch (Throwable ex)
{
ex.printStackTrace();
}
finally
{
if (socket != null)
{
socket.close();
}
}
}
}
readLine(); will read (or block) until it encounters a line feed, so that's why you're getting stuck. However you didn't use a line feed in the command you sent either, which is suspicious since there must be some agreed form in the protocol to be able to tell commands apart (flush() is not enough).
I suspect the plotter is still waiting for you to finish your command with a \nbefore you can read anything it returns.

Java Chat Server (Socket) - how to write unit test?

I have written a Java Chat Server program.
This is a simple standalone program for Server.
I have to run this then run Client to get Chat working.
What are some possible Unit Test scenarios for the server program? Can anyone show me some example of unit test based on this code?
I have never written a unit test code before and I can't really think of what needs to be tested here.. I think testing Connection can be one but what else? (and how to?)
public class SimpleChatServer {
static final Logger logger = LogManager.getLogger(SimpleChatServer.class);
ArrayList<PrintWriter> clientOutputStreams;
private BufferedReader reader;
private Socket sock;
private ServerSocket serverSock;
public class ClientHandler implements Runnable{
public ClientHandler(Socket clientSocket){ // Socket Connection
try {
sock = clientSocket;
InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(isReader);
} catch(Exception ex) {
logger.trace(ex);
}
}
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
tellEveryone(message);
}
} catch(Exception ex) {
logger.trace(ex);
}
} //close run
} //close ClientHandler
public static void main (String[] args) throws Exception
{
new SimpleChatServer().listen();
}
#SuppressWarnings("resource")
public void listen()
{
clientOutputStreams = new ArrayList<PrintWriter>();
try {
ServerSocket serverSock = new ServerSocket(8000); //port number 8000 was used
while(true) {
Socket clientSocket = serverSock.accept();
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
clientOutputStreams.add(writer);
Thread t = new Thread(new ClientHandler(clientSocket));
t.start();
}
} catch (Exception ex) {
logger.trace("Server Error", ex);
} finally {
try
{
serverSock.close();
}
catch(Exception e){}
}
} // close go
public void tellEveryone(String message)
{
Iterator<PrintWriter> it = clientOutputStreams.iterator();
while(it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch (Exception ex) {
logger.trace(ex);
}
} // end while
} // close tellEveryone
}
I was going to crib an answer from Pragmatic Unit Testing, but suggest you just find a copy. At the very least you should consider whether results are right, whether your boundary conditions are correct, and if you can force error conditions.
Testing results often means making sure combinations of input get the expected results. Boundaries are reflected in the related "0, 1, many" rule, where you do silly stuff to see if your code has implicit boundaries that can be reached with bad, null or unexpected values.
For example, what happens if you pass huge Strings to your methods that take them? What about strings with weird Unicode chars in them? No line breaks?
Forcing error conditions means making sure things degrade gracefully and/or throw under the expected situation.
Think about your code as a brittle little appliance and then pretend a poo-flinging monkey, a 14-yr old hacker and your non-hacker grandmother (I know some exist) are all taking turns on it.

what is blocking the readLine() in this case? I tried sending \n or even byte arrays, is it a concurrency issue in my case?

I tried everything stack overflow has to offer on this common readLine problem. (sending \n, flushing out, changing to byte array style, becoming hermit, wrists )
I suspect in this case its a concurrency thing as Ispent well over 15 hours yesterday confirming that the only thing that isnt working is readline()!
I used loads of other versions like datareader with a byte array and making sure a \n got sent I even sent /ns just in case!
still my issue is the same, and I have ran out of ideas myself to solve the issue and have decided that somewhere, my problem is outside my understanding, just where? its got to be threading right?
I managed to get to read the socket to string that seemed to work so it IS blocking because reading the connection isnt working at all, the readline function is not the only way Ive had it as I said so in my snippets its not as developed as it has been but still the basic issue remains.
Please help, i dont know what the issue is
// So the main class initialises the socket objects and starts them in a thread, these work I get all sorts of flags letting me know that they are
void start_sockets() {
//if this is initiialised as a server and not a client
if (is_server) {
while (is_server) {
try {
System.out.println("listening for connection");
Sockject sj = new Sockject(server.accept());
sock_arr.add(sj);
System.out.println("server made connection ");
// once the connection is made the objects is started in a
// separate thread
new Thread(sock_arr.get(sock_arr.size() - 1)).start();
} catch (IOException e) {
}
}
} else { //else im running a client version of this class
// if the client socket isnt running in a thread, make it run
if (!running) {
new Thread(sj_client).start();
if (sj_client.sock.isConnected()) {
System.out.println("client thread connected to "
+ sj_client.sock.getLocalSocketAddress());
running = true;
}
}
}
}
//the inner class creates a socket object and puts it on an array or an object depending if the parent class is initialised to be a server or a client
class Sockject implements Runnable {
PrintWriter out;
BufferedReader in;
// a socket for processing
Socket sock;
// the constructor in this case initialises the input and output streams
Sockject(Socket s) {
sock = s;
try {
out = new PrintWriter(sock.getOutputStream());
in = new BufferedReader(new InputStreamReader(
this.sock.getInputStream()));
} catch (IOException e) {
close sockets
}
}
//tried variasions of this and similar, used data objects and been sennding /ns all over the shop
void recieve_data() throws IOException {
if (sock.isConnected()) {
if ((recieve = in.readLine()) != null) {
System.out.println("recieve says " + recieve);
}
}
}
// sends data to connection if it is cleared to send data
void send_data(String data) {
// send data called
if (clear_to_send == true) {
out.print(data);
out.flush();
clear_to_send = false;
}
}
#Override
public void run() {
while (threadloop ) {
try {
//code defo gets this far and with just send it keeps running forever so its defo recieve data thats the issue
send_data(send);
recieve_data();// <---I HATE YOU
} catch (IOException e) {
}
}
}
}
}
Now all of the above is ran in an instance of this class, in a thread of this class here these temporary functions are ran and are neversuccesfull
void servrecievex(){
System.out.println("NEVER GETS THIS FA THOUGH DOES IT");
for(int a = 0; a < net_flow.sock_arr.size(); a++){
if(net_flow.sock_arr.get(a).sock.isConnected()){
System.out.println("server recieve function");
net_flow.sj_client.clear_to_send = true;
net_flow.sock_arr.get(a).send_data("www /n \n");
System.out.println("RECIVEIFY!!!");
}
}
}
void clientsendx() {
net_flow.sj_client.clear_to_send = true;
net_flow.sj_client.send_data(Integer.toString(player1.posx) + "\n");
System.out.println("client sent stuff");
}

java socket disconnected from server side

I am facing a problem regarding sockets on the server side. My code is client side. Whenever I am sending a second message (whether it's a heartbeat or any other message) it will fail on the server, and the server side logs an 'error in message format' but the same message will succeed the first time.
Please help me out with this.
my client code :
public class Main {
String Host = "";
int port = 1111;
Socket ss;
BufferedReader in;
BufferedWriter out;
String recv;
public void connection() {
try {
ss = new Socket(Host, port);
ss.setSoTimeout(30000);
in = new BufferedReader(new InputStreamReader(ss.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(ss.getOutputStream()));
} catch (UnknownHostException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sender(String regTag) {
if (ss == null || !ss.isConnected()) {
connection();
}
try {
if (out != null && regTag != null) {
out.write(regTag + "\n");
System.out.println("message::" + regTag);
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String Reciver() {
try {
recv = in.readLine();
if (ss != null && recv != null) {
return recv;
} else {
disconnect();
String Str = "nothing...Sorry";
return Str;
}
} catch (Exception e) {
e.printStackTrace();
return "Exception";
}
}
public void disconnect() {
try {
System.out.println("socket discoonected.");
ss.close();
in.close();
out.close();
connection();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Main me = new Main();
me.connection();
String hbhb = "`SC`0004HBHBB7BDB7BD";
String login = "`SC`00581.000000CRBTSRVM 00000001DLGLGN 00000002 TXBEG LOGIN:USER=cvbs,PSWD=password DEB2CCA8";
String cut = "`SC`00631.000000CRBT00PPSPHS00000002DLGCON 00000003 TXBEG CUT PPS FEE:MDN=9610023,CUTFEE=1000,REASON=1 BDB7DA88";
me.sender(hbhb.trim());
String str = me.Reciver();
System.out.println("Response :::" + str);
me.sender(login.trim());
String str1 = me.Reciver();
System.out.println("Response hb:::" + str1);
}
It receives null ... all the time on every second message
logs from serverside
[121_SERVER] 2012-05-03 14:26:37:213 [ERROR] [ServerAccptor.java:254] ->
errorCode = [UIP-80015] errorDesc = [Uip server has a exception when receiving data from the client,will remove the client,Server [adapter id=121],.]
at com.ztesoft.zsmart.bss.uip.adapter.socket.server.ServerAccptor.listenMsg(ServerAccptor.java:252)
at com.ztesoft.zsmart.bss.uip.adapter.socket.server.ServerAccptor.run(ServerAccptor.java:117)
Caused by: errorCode = [UIP-9102] errorDesc = [] Describing= [read client message error,will remove client.]
at com.ztesoft.zsmart.bss.uip.adapters.socket.server.mml.MMLServerAdapter.readByteField(MMLServerAdapter.java:784)
at com.ztesoft.zsmart.bss.uip.adapters.socket.server.mml.MMLServerAdapter.reciveWholeMsg(MMLServerAdapter.java:671)
Your code embodies numerous bad practices and fallacies.
You are logging exceptions and otherwise ignoring them, and doing strange things like letting the program continue, returning "Exception", etc. This is poor programming. Exceptions are there to help you, not to have bandaids applied them to hide the blood. The code will not self-heal under the bandaid. For example you should just declare connection() to throw IOException and let the callers deal with it.
As a consequence of (1) you have numerous ss != null tests. You shouldn't even be in a state where you need to do I/O and ss could be null. Again correct exception handling and propagation would avoid this.
As a further result of (1), you have numerous !ss.isConnected() tests, apparently in the mistaken belief that this API will tell you if the connection has been dropped. It won't. It will only tell you whether you have connected the Socket yet. In your code, as you are calling ss = new Socket(...), you have connected it, or else you haven't executed that code yet. Calling isConnected() adds no value.
You are closing the socket input stream before the output stream. This is incorrect. You should close only the output stream, and the socket itself in a finally block. That way the output stream gets flushed. Closing the input stream closes the socket and the output stream without flushing it. Don't do that.
Actually the correct answer is that there is no \n in the MML response. So this never works:
recv = in.readLine();
You have to read the message length given in the message header part of the response and read up to that length.
UPDATE:
there are syntax errors in your MML commands. It seems that you are using version 1.00 of the protocol, so this is a sample that works (look for differences):
`SC`00741.00CRBT PPS 00000001DLGCON 00000004TXBEG PPS CUT FEE:mdn=93784050910,fee=300,id=20140812165011003 F3E0ADDF
You must fill the extra spaces with 0 just in numbers, elsewhere you have to fill them with blank spaces.

java socket server, client detect server has died

If I kill the Socket Server process, my Socket client process does not receive any errors, it continues to loop forever on the following code:
public void run() {
while(readData) {
String inputLine = null;
try {
while((inputLine = m_inputStream.readLine()) != null) {
//do stuff
}
} catch (IOException e) {
readData = false;
}
}
}
How can I detect that the socket server is gone and terminate the loop?
Terminate the outer loop when the call to readLine() returns null.
No exception is thrown when the server closes the connection normally. The stream should return null to signal the end of data.
This can be done with a loop like this:
public void run() {
try {
while (true) {
String line = input.readLine();
if (line == null)
break;
/* Process line. */
...
}
} catch (IOException ex) {
/* Handle the exception as desired. */
ex.printStackTrace();
}
}
Whilst the answer from erickson is correct, have you tried setting the socket read time-out properties? (e.g. sun.net.client.defaultReadTimeout). If it is possible that the server may take a long time responding, then this might be less useful as a solution to your problem but is a good idea nevertheless in many scenarios.

Categories