Best programming way to read streaming data - java

I am reading a streaming data from an TCP streaming software. I'm currently using while loop to read continuously. But I am not sure that if this is the best technique to read streaming data.
Following is the code i'm currently using:
Socket client=new Socket("169.254.99.2",1234);
System.out.println("Client connected ");
//getting the o/p stream of that connection
PrintStream out=new PrintStream(client.getOutputStream());
out.print("Hello from client\n");
out.flush();
//reading the response using input stream
BufferedReader in= new BufferedReader(new InputStreamReader(client.getInputStream()));
int a = 1;
int b= 1;
//
while(a==b){
// I'm just printing it out.
System.out.println("Response" + in.read());
}
Suggestions plz???

That loop would be the same as while(true), which is continuous. Also, I suggest running this in a thread.
After you init your socket and streams, I suggest calling a method like this:
Thread messageThread;
public void chatWithServer() {
messageThread = new Thread(new Runnable() {
public void run() {
String serverInput;
while((serverInput = in.readLine()) != null) {
//do code here
}
}
};
messageThread.start();
}
We put it in a thread so the loop doesn't hold up the rest of the client's code. (does not progress after loop)
The while loop initilizes serverInput within the parameters, so each time it loops, it re-inits serverInput so it doesn't constantly loop with the very first sent piece of data.
You gotta put it in parenthesis, because of course, while loops only accept boolean parameters (true/false). So, in pseudocode, if the InputStream always returns something, continue with the new recieved data.

I'm currently using while loop to read continuously.
That is the best technique for reading streaming data. However your loop must test for end of stream, which is signalled by read() retuning -1 in Java. Your 'a==b' test is pointless. There are several possible loop tests:
while (true) // with a break when you detect EOS
Or
while ((c = in.read()) != -1)
where 'c' is an 'int'.
But I am not sure that if this is the best technique to read streaming data.
Why not?

Related

Separating Get request Response body in java Socket programming

I'm trying to write a curl like program using java, which uses only java socket programming (and not apache http client or any other APIs)
I want to have the option of showing whole or only the body of the response to my get request to user. Currently came up with the following code:
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String t;
while ((t = br.readLine()) != null) {
if (t.isEmpty() && !parameters.isVerbose()) {
StringBuilder responseData = new StringBuilder();
while ((t = br.readLine()) != null) {
responseData.append(t).append("\r\n");
}
System.out.println(responseData.toString());
parameters.verbose = false;
break;
} else if(parameters.isVerbose())// handle output
System.out.println(t);
}
br.close();
When the verbose option is on, it works quick and shows the whole response body in less than a second. but when I want to just have the body of the message it takes too much time(approx 10 sec) to hand it out.
Does any one knows how can it be processed in a faster way?
Thank you.
I'm going to assume what you mean by slow is that it starts displaying something almost immediately but keeps on printing lines for a long time. Writing to the console takes time, and you're printing each line invidually while in the other code path you first store the entire response in memory and then flush it to the console.
If the verbose response is small enough to fit in memory, you should do the same, otherwise you can decide on an arbitrary number of lines to print in batches (i.e; you accumulate n lines in memory and then flush to the console, clear the StringBuilderand repeat).
The most elegant way to implement my suggestion is to use a PrintStream wrapping a BufferedOutputStream, itself wrapping System.out. All my comments and advices are condensed in the following snippet:
private static final int BUFFER_SIZE = 4096;
public static void printResponse(Socket socket, Parameters parameters) throws IOException {
try (BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream printStream = new PrintStream(new BufferedOutputStream(System.out, BUFFER_SIZE))) {
// there is no functional difference in your code between the verbose and non-verbose code paths
// (they have the same output). That's a bug, but I'm not fixing it in my snippet as I don't know
// what you intended to do.
br.lines().forEach(line -> printStream.append(line).append("\r\n"));
}
}
If it uses any language construct you don't know about, feel free to ask further questions.

the proper way to listen for server sending attempt

what is the proper way to determine that the server is sending data at the moment for example
Pseudo-code
while(true){
//Do something
if(ServerIsSendingrightnow){
//Get The Data
//Calling some method to handling the server's data
}
//Do something else
}
does the method available() of InputStream class do the job ?
Code:
while(true){
//Do something
InputStream IStreamsock = Socket1.getInputStream();
if(IStreamsock.available()){ //the server is sending data right now !
//Get The Data
//Calling some method to handling the server's data}
//Do something else
}
In C# we have MemoryStream class that serve as Dynamic byte array
is there any java equivalent for MemoryStream
can I do something like this in java:
Pseudo-code
while(DataIsAvailableInSocketInputStreamBuffer){
MemoryStreamEquivalent.WriteByte(IStreamsock.ReadByte())}
I'm Sorry, but I'm new comer in java
Nope, the usage of available is not very useful, because it does not work as you would expect it. Just use in.read(). It will wait until something is sended by the server. So if you use it in a thread, it just waits until something can be recieved.
Edit: It recieves just one Byte, so e.g. a BufferedReader (to read Strings) is a better solution, or maybe an ObjectInputReader (for Objects, obviously). And of course the while(true) is needed :)
Example:
Socket s = new Socket(...); // connect to server
BufferedReader br = new BufferedReader(s.getInputStream()); // creating a bufferedReader around the inputstream. If you're dealing with binary data, you shouldn't create a (Buffered)Reader
while (String line = br.readLine()) {
//do something here
}
So here is an answer how you could do this:
(I wrote a complete example run() method of the client thread
#Override
public void run() {
while(client.isConnected()) { //client.isConnected should be a method of your client class
Object inputData = in.read(); //you should use a proper Object type here, if you
//use InputStreamReader, it would be Byte and if you
//use BufferedReader it would be String
doCrazyStuff(inputData); //just an example of manipulating data, do your own stuff here
}
}
Here an example with BufferedReader (I will not change the encoding or something, because I think this is just a training application)
public void run() {
while(client.isConnected()) { //client.isConnected should be a method of your client class
while(!in.ready()) { } //here you CAN use the method ready, that is boolean
String inputData = in.readLine();
doCrazyStuff(inputData); //just an example of manipulating data, do your own stuff here
}
}

Reading from a socket in a while loop

I want to implement the following functionality
while (true)
{
if client sends something
process it
else wait till something is send }
I have tried the following but it didn't work , it process one thing and then stop working
can anyone help me?
I have searched for such a case here but I didn't find anything . I would appreciate it if anyone can give an example of how to read from the socket inside a while loop as in the above description .
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
DataOutputStream outToclient =new DataOutputStream(client.getOutputStream());
while (true){
if ((request=inFromClient.readLine())!=null){
System.out.println("ser "+request);
msg1= new msgs();
if(msg1.IsListReq(request))
{
System.out.println("Ser :List req");
for (int i = 0; i <listOfFiles.length ; i++)
{
if (listOfFiles[i].isFile())
{
files[i] = listOfFiles[i].getName();
}
}
//prepare the respones
msg1.MakeFileListResponse (files);
outToclient.writeBytes(msg1.getMsg()+'\n');
} // end of processing List Request
} // end of first if statement
} end of while loop
You should have a condition to break your while loop or it will loop forever and your program will crash. This could be the problem you have.
Right now, you have an infinite loop. This differs from "read as long as there is input available" in that it will continue to read after input is no longer available.
Try something like this:
do
{
request = inFromClient.readLine();
if (request != null)
{
// do stuff.
}
} while (request != null);
The example above will stop reading when input is no longer available from the input stream.
For information about java and sockets check out the Oracle Java Socket Tutorial.
The work you describe will reside on a server.

Java: Getting multiple lines from socket

I have a Java application that consists of a client and a server. The client sends encrypted commands to the server, and the server executes them.
The problem that I am having right now is that, with my encryption algorithm, sometimes the encrypted command contains "\n" or "\r" characters, which mess up my server code. This is because I am using the readLine() method, which stops when it finds a line terminator. What I need is a way to read all the characters the client sends into one string.
Here is my code:
public void run(){
System.out.println("Accepted Client!");
try{
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "ISO8859_1"));
out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "ISO8859_1"));
String clientCommand = null;
while(RunThread){
// read incoming stream
do{
clientCommand = in.readLine();
}while(clientCommand == null);
//decrypt the data
System.out.println("Client: " + clientCommand);
if(clientCommand.equalsIgnoreCase("quit")){
RunThread = false;
}else{
//do something
out.flush();
}
}
}catch(Exception e){
e.printStackTrace();
}
}
Everything I've tried (various forms of nested loops using the read() function) hasn't worked. I would welcome any help or suggestions. Thanks, everyone!
I don't see encryption in the code you posted, but usually it's not a good idea to rely on separator characters.
When sending binary data, you should prepend the length of the data to the stream, and then you know exactly how many bytes to expect (and when the message will end.) It's more efficient to do things that way too instead of looking for a newline character.
// read incoming stream
do{
clientCommand = in.readLine();
}while(clientCommand == null);
That == null seems wrong
Try
String line = null;
do {
line = in.readLine ();
clientCommand += line
} while (line != null);
One thing you must do, when working with TCP/IP, is to send the message length before the actual message. The application level cannot foresee the package size the TCP level is delivering to the destiny. So, before your message, you have to send a header with the message size and the destiny would read just these bytes.
About readLine(), I think it's better use another approaches like streams. Shortly, one suggestion:
Socket oSocket = new Socket(sAddress, iPort);
PrintWriter out = new PrintWriter(oSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(oSocket.getInputStream()));
do{
clientCommand = in.readLine();
} while(clientCommand == null);
This makes no sense. readLine() only returns null at end of stream, so you are telling Java to loop infinitely at end of stream. I don't even understand why there is a loop at all. You don't want to ignore any input from the client, you want to process it all. You should read one line from the client, execute it, and read another line. Repeat until null, then close the socket.

Java read serial data for given time period.

I have a function that reads serial data from an embedded device. My program shows a picture and a title and basically the device acts as a buzzer for a game. Is there a way to check for serial data for lets say 5 seconds and if nothing was received to continue with the code (go to the next picture and title). My current function looks like this.
public String getUARTLine(){
String inputLine = null;
try{
BufferedReader input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
inputLine = input.readLine();
if (inputLine.length() == 0)
return null;
} catch (IOException e){
//System.out.println("IOException: " + e);
return null;
}
return inputLine;
}
You can start reading data from serialPort and start a timer in other thread. Something like this:
class ReadItWithTimeLimit implements Runnable {
int miliSeconds;
BufferedReader reader;
public ReadItWithTimeLimit (BufferedReader reader, int miliSeconds) {
this.miliSeconds = miliSeconds;
this.reader = reader;
}
public void run() {
Thread.sleep(miliSeconds);
this.reader.close();
}
}
So you can call it from your code:
// ...
BufferedReader input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
new Thread(new ReadItWithTimeLimit(input, 5000)).start();
inputLine = input.readLine();
// ...
This code is without excaption handling, so it requires some finalization work...
Drop the buffer. Start a read on the input stream yourself and in a different thread count 5 seconds. After that, close the stream (that will cause the read function to return -1).
Yes you can. You can use a separate timer thread that triggers the timeout that closes the input stream (that will cause input.readLine() to come back with an IOException). Or you can use java.nio. However I personally prefer the first method.

Categories