I'm building a web server and client which I will use on a Raspberry Pi. The server is written in Python and every time a client connects to it, it will return data to the client. This is working well and when I access the server through my browser, I see the correct data and when I refresh the page I get new data, so that is working.
The problem is that I'm now writing a client in Java to access the server and collect the data. The reason I use here Java is that I'm more experienced in it and I find building a GUI more convenient; I use python on the raspberry pi because it offers me a simpler way of interacting with the hardware.
The java client code I have is this:
while (true) {
Socket socket = new Socket("192.168.0.37", 9315);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
try {
System.out.println("Getting");
out.write("GIMME DATA!");
out.flush();
System.out.println("receiving");
String data;
while ((data = in.readLine()) != null) {
System.out.println("Line: " + data);
}
socket.close();
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
}
This all works well, but I want to take the initial 3 objects out of the while loop (and obviously not close the connection). When I do that, I only can access the server once (it will give me the correct data) and on the second run in.readling() will return null which is weird. It seems that the inputstream only has the data from the initial run and no more bytes are written to it. To be clear, when putting the initial 3 objects IN the while loop, everything works well.
How can I take the objects out of the loop? It seems wasteful, time consuming and possibly memory consuming to create them every time...
Once you have reached to end of the file or BufferedReader reached to end of data, then how can it print again data from beginning. For example :
int i = 0;
BufferedReader br = new BufferedReader(new FileReader(new File("C:\\data.txt")));
while (true) {
String data = "";
while ((data = br.readLine()) != null) {
System.out.println(" data :" + data);
}
Thread.sleep(1000);
i++;
if (i == 2) {
break;
}
}
br.close();
In the above program, br reached to end of file, then it cannot point to the beginning. You have to create BufferedReder object every time when you enter while loop.
Related
I've been making a chat room where multiple clients can connect and talk together on the same server. The only problem I'm having is getting each client to send more than one message. I've been trying different ways of looping the method to do so but I'm having some issues.
Any help would be appreciated :) thank you.
HERE'S THE CODE:
public class Client {
public static void main(String[] args){
Scanner clientInput = new Scanner(System.in);
try {
Socket SOCK = new Socket("localhost", 14001);
System.out.println("Client started!");
//Streams
while(true){
OutputStream OUT = SOCK.getOutputStream(); //writing data to a destination
PrintWriter WRITE = new PrintWriter(OUT); // PrintWriter prints formatted representations of objects to a text-output stream
InputStream in = SOCK.getInputStream(); //reads data from a source
BufferedReader READ = new BufferedReader(new InputStreamReader(in));
//---------------------------------
System.out.print("My input: ");
String atServer = clientInput.nextLine();
WRITE.write(atServer + "\n");
WRITE.flush(); //flushes the stream
String stream = null;
while((stream = READ.readLine()) != null){ //if stream is not empty
System.out.println("Client said: " + stream);
}
READ.close();
WRITE.close();
}
} catch (UnknownHostException e){
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
I've tried using a while loop to continuously ask for an input but doesn't seem to be working.
Are you making it out of the READ.readLine() while loop? Perhaps you're never getting an end of input character and thats never terminating. Also, you're closing both your READ and WRITE at the end of the while loop, and then expect them to be open on the next iteration. Move those and the close statements to the same layer as the Socket.
With that, every time you send something, your client is expecting something in response from the server. If you don't want them to be dependent on each other, I recommend moving the receive logic to its own thread in a while(true) loop.
I've gone through so many related StackOverflow questions for this that I'm getting lost in them, and I've coded this multiple ways, but none seem to solve this problem in a way that works for me: How can I send output to the same command and process multiple times while at the same time receiving input from this same process?
(See Input various strings to same process in Java for a similar question, but this ended with only a theoretical answer.)
The command (command line, from a C++ executable) loads a large file, and then I want to send input to it very quickly, get back the answer, do other stuff in between, then send different input and get the corresponding answer. Multiply this by thousands or millions of times.
One implementation, with threads:
ProcessBuilder pb = new ProcessBuilder(command.split(" "));
kenLMProcess = pb.start();
KenLMInThread lmInput = new KenLMInThread(kenLMProcess.getInputStream());
KenLMInThread lmError = new KenLMInThread(kenLMProcess.getErrorStream());
KenLMOutThread lmOutput = new KenLMOutThread(kenLMProcess.getOutputStream());
lmOutput.inStr = "Test . \n";
lmInput.start();
lmOutput.start();
lmError.start();
lmOutput.join();
lmInput.join();
lmError.join();
outStr = lmInput.newStr;
But join waits until the thread ends. What if I don't want to wait for it to end? I can't seem to figure out how to use wait() for that purpose. For one I'd prefer to not have to keep opening and closing a new output stream and input stream every time I query the command. But at least that's better than starting a new ProcessBuilder every time.
Here's what run() looks like for KenLMOutThread:
public void run() {
try {
pw.write(inStr+"\n");
pw.write('\n');
} catch (Exception e) {
System.out.println("Error while inputting to KenLM.");
e.printStackTrace();
} finally {
pw.flush();
try {
pw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Supposedly flush is supposed to let it move on, and "\n" at the end is supposed to help, but it just hangs unless I use close. And if I use close, I can't use the OutputStream anymore. I'm also then unable to make a new OutputStream from the Process.
If it helps, here's a more simple implementation with everything together (taken from How to send EOF to a process in Java?):
Note that close() is used, and using flush() without close() causes the program to hang.
public static String pipe(String str, String command2) throws IOException, InterruptedException {
Process p2 = Runtime.getRuntime().exec(command2);
OutputStream out = p2.getOutputStream();
out.write(str.getBytes());
out.close();
p2.waitFor();
BufferedReader reader
= new BufferedReader(new InputStreamReader(p2.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
return sb.toString();
}
Other things I've tried:
Using exec(): Process kenLMProcess=Runtime.getRuntime().exec(command);
Putting the command process in its own thread: KenLMProcessThread procThread = new KenLMProcessThread(pb.start());
If the target process is hanging unless you close the output stream, the problem is at that end: it is reading until end of stream before doing anything. Nothing you can do about that at the sending end.
I am using Java as a front end for a chess AI i am writing. The Java handles all the graphics, and then executes some C using a few command line arguments. Sometimes the C will never finish, and not get back to the Java. I have found cases in which this happens, and tested them with just the .exe and no java. When i take out the java, these cases work everytime. I am not sure where to go from here. Here is some code that i think is relavant, and the whole project as at https://github.com/AndyGrant/JChess
try{
Process engine = Runtime.getRuntime().exec(buildCommandLineExecuteString(lastMove));
engine.waitFor();
int AImoveIndex = engine.exitValue();
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(engine.getInputStream()));
while ((line = input.readLine()) != null)
System.out.println(line);
input.close();
if (AImoveIndex == -1){
activeGame = false;
System.out.println("Fatal Error");
while (true){
}
}
else{
JMove AIMove = JChessEngine.getAllValid(types,colors,moved,lastMove,!gameTurn).get(AImoveIndex);
AIMove.makeMove(types,colors,moved);
lastMove = AIMove;
validMoves = JChessEngine.getAllValid(types,colors,moved,lastMove,gameTurn);
}
waitingOnComputer = false;
parent.repaint();
}
catch(Exception e){
e.printStackTrace();
}
Sometimes, the external process will get stuck on IO, trying to write to the console. If the console buffer is full, the next printf will block.
How much text is it writing to the console?
Try moving your engine.waitFor() after the part where you read all the input from it.
An alternative would be to have the external process write to a temp file, and then you read the temp file.
Maybe remove
while (true){
}
If your AImoveIndex == -1, your program will enter in a never ending 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.
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.