Is there any way to make the method readline() (from bufferedReader) block until it has in fact something to read??
I'm creating an client/server application socketBased and I have this
The Server reads and then writes. The Client writes and then reads.. this is the communication between client/server (based on sockets)
The only problem is that on the server I'm reading with bufferedReader.readLine() which isn't a blocking method. I have already tried replacing the bufferedReader.readLine() by dataInputstream().read() (handle all the byte stuffs and getting out when -1 is received) and it isn't working either.
The problem in all this is that the server is expecting to read but do not blocks. the client is only going to write to the server (through a socket) when the user press a button (so the server must be waiting for reading and it is not)
On the server side i have this:
BufferedReader READ = new BufferedReader(new InputStreamReader(skt.getInputStream()));
BufferedWriter WRITE = new BufferedWriter(new OutputStreamWriter(skt.getOutputStream()));
FileInputStream fstream = new FileInputStream(file);
DataInputStream in = new DataInputStream(fstream);
boolean FLAG = true;
String s = new String("#$");
while (FLAG) {
if (skt == null)
FLAG = false;
// READING FROM THE CLIENT
while (!READ.ready()){System.out.println("Blocking")};
while ((s = READ.readLine()) != null) {
System.out.println("RECEIVING: " + s);
System.out.println("$$$");
}
System.out.print("hi");
// READING FROM THE FILE AND SENDING TO THE CLIENT
//WRITTING TO THE CLIENT
while ((strLine = in.readLine()) != null) {
System.out.println("SENDING: " + strLine);
strLine += "\n";
WRITE.write(strLine);
WRITE.flush();
strLine = new String();
}
}
On the Client side i have this:
//READING FROM THE FILE AND SENDING TO THE SERVER
while((strLine = in.readLine()) != null)
{
strLine += "\n";
soma+=strLine.length();
WRITE.write(strLine);
WRITE.flush();
TextArea1.append(strLine);
ProgressBar.setValue(soma);
ProgressBar.repaint();
};
in.close();
ProgressBar.setValue(0);
soma=0;
//READING FROM THE SERVER
while((strLine=READ.readLine()) != null)
{
strLine+="\n";
soma+=strLine.length();
TextArea2.append(strLine);
strLine = new String();
ProgressBar.setValue(soma);
ProgressBar.repaint();
}
in.close();
fstream.close();
WRITE.close();
READ.close();
Skt.close();
NOTE: Skt is a socket connecting client to server.
the problem here is that. When the client connects to the server, the server expects to read from the socket right after the connection is established.. however the code on the client (writing to the server) is only expected to run when the user presses a button.. So, the server must be blocked until the client in fact writes something to the socket which is not (the server is not blocking). :-/ hope to make my self more clear this time.. Sorry
BufferedReader.readLine() always blocks until it finds '\n'.
If you can give examples of data you're sending around, I might help you further.
Try to use file lock approach like:
file = new RandomAccessFile("file.txt", "rw");
FileChannel channel = file.getChannel();
fl = channel.tryLock();
// file now is locked
fl.release();
Related
I'm trying to make a chat application between a server and clients which are seperate classes. I'm not copying the whole code, but this is the part I'm not sure is set up correctly:
Server:
ServerSocket s = null;
Socket c = null;
s = new ServerSocket(5002);
c = s.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()))
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(c.getOutputStream()));
out.flush();
String line;
line = in.readLine();
out.write("#W|Welcome");
line = in.readLine();
out.write("#W|Welcome");
line = in.readLine();
out.write("#W|Welcome");
Client :
Socket socket = new Socket("localhost", 5002);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream ()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
out.flush();
out.write("#J|test");
line = in.readLine();
out.write("#J|test");
line = in.readLine();
After the client does out.println(), the server's in.readLine() gets the line. But when it's the other way around, the client keeps waiting at in.readLine(). (I used the debugger and watched the server execute out.println() and go past it, while the client is still stuck at in.readLine().
Are my data streams set up correctly or is there probably an error in my code somewhere else? I'm not sure how to check in the debugger if the streams are connected correctly.
[Quoting my comment above:]
There is nothing here that [reads or] writes lines.
That remains true. All you have is:
out.write("#W|Welcome");
etc.
don't forget to call newLine() as necessary
You forgot.
I'm working on a TCP client/server application and face the issue that the client is always blocking at br.readLine(). I tried to add a \n, but it did not solve the problem. Also a char array is blocking, when I only use read instead of readLine.
Client:
BufferedReader brInput = new BufferedReader(new InputStreamReader(System.in));
String send = brInput.readLine();
Socket socket = new Socket(host, port);
BufferedReader brSend = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pr = new PrintWriter(socket.getOutputStream());
pr.println(send);
pr.flush();
System.out.println(brSend.readLine()); // is blocking
socket.close();
Server:
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
Socket socket = serverSocket.accept(); // blocks until request is received
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
if (line.isEmpty()) break;
}
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.write("Hello world\n");
pw.flush();
pw.close();
socket.close();
}
Your code as written does this:
The client writes one line, and then tries to read one.
The server reads multiple lines until it either gets an empty line, or the end-of-stream. Then it writes a line.
The problem is that server is waiting for the client to do something that it isn't going to do:
the client won't send an empty line (unless it read one from standard input),
the client won't close the stream ... until it gets the response from the server.
Hence the client is waiting for the server and the server is waiting for the client. Deadlock.
There are various ways to solve this. One simple way would be to change this (in the client)
println(send);
to this
println(send); println();
However, the one problem here is that your "protocol" does not cope with the case wants to send an empty line as data. That is because you are implicitly using an empty line (from the client) to mean "message completed".
I am practicing a simple java program where I am demonstrating simple client server interaction. The fist part of message from server gets transferred. Then program just continues to run and does not execute? Do we need to create a new socket for each individual traffic?
Server code
server = new ServerSocket(4587);
System.out.print("Starting the Server on port " + server.getLocalPort() + "\n");
System.out.println("Waiting for client...");
Socket client = server.accept();
BufferedWriter br = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
BufferedReader br1 = new BufferedReader(new InputStreamReader(client.getInputStream()));
br.write("Hello, you are connected to Server. What is your name?");
br.write("\n");
br.flush();
while((s=br1.readLine())!=null)
{
}
br.write("Thank you ");
br.newLine();
br.flush();
}
Client code
String stdin;
System.out.println("Attempting to connect to " + hostname + ":" + port);
client = new Socket("localhost", 4587);
System.out.println("Connection Established");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while ((stdin = br.readLine()) != null) {
System.out.println(stdin);
}
BufferedWriter br1 = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
br1.write("Mike");
br1.write("\n");
br1.flush();
while ((stdin = br.readLine()) != null) {
System.out.println(stdin);
}
Server Output
Starting the Server on port4587
Waiting for client....
Client Output
Attempting to connect to :123
Connection Established
Hello you are connected to Server, What is ur name
If this could help..after this both loop
Your server will first create a connection with the client through the accept method. If you wish to have multiple clients you will need to change your code accordingly to accept that.
On the client side, you're using \n to delineate the end of a message. This will work fine. Every time you send a new message use \n to indicate the end of the message.
On the server side, you should continue reading from I/O until you see the \n. At that point you have received the entire message. Process it and than start listening again.
Edit:
Since you are waiting for the name of the client, you could simply do the following on the server:
BufferedWriter bout = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
BufferedReader bin = new BufferedReader(new InputStreamWriter(client.getInputStream()));
// Wait for incoming name from client.
String name = bin.readline();
System.out.println(name);
// Send a reply.
bout.write("Thank you\n");
bout.flush();
Similarly, on the client (assuming bin and bout are defined the same as above):
// Send name to server.
bout.write("Name\n");
bout.flush();
// Get a response from the server and print to console.
String response = bin.readline();
System.out.println(response);
This is because BufferedReader has a default buffer = 8K when in reading process and this process is block I/O, so this will hang in that point. You should read the full message from client by server side.
Your problem is with the loop on the client side. It will be stuck in the loop as it waits to readlines sent from the server infinitely. (ie, after reading the first line from the server, it will expect more lines from the server and wait to read them).
To exit the loop you need to send an EOF signal or end of stream signal (according to the docs: http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#readLine%28%29)
I have a Socket listening on some x port.
I can send the data to the socket from my client app but unable to get any response from the server socket.
BufferedReader bis = new BufferedReader(new
InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = bis.readLine()) != null)
{
instr.append(inputLine);
}
This code part reads data from server.
But I can't read anything from server until unless the Socket on the server is closed.
Server code is not under my control to edit something on it.
How can I overcome this from client code.
Thanks
Looks like the server may not be sending newline characters (which is what the readLine() is looking for). Try something that does not rely on that. Here's an example that uses the buffer approach:
Socket clientSocket = new Socket("www.google.com", 80);
InputStream is = clientSocket.getInputStream();
PrintWriter pw = new PrintWriter(clientSocket.getOutputStream());
pw.println("GET / HTTP/1.0");
pw.println();
pw.flush();
byte[] buffer = new byte[1024];
int read;
while((read = is.read(buffer)) != -1) {
String output = new String(buffer, 0, read);
System.out.print(output);
System.out.flush();
};
clientSocket.close();
To communicate between a client and a server, a protocol needs to be well defined.
The client code blocks until a line is received from the server, or the socket is closed. You said that you only receive something once the socket is closed. So it probably means that the server doesn't send lines of text ended by an EOL character. The readLine() method thus blocks until such a character is found in the stream, or the socket is closed. Don't use readLine() if the server doesn't send lines. Use the method appropriate for the defined protocol (which we don't know).
For me this code is strange:
bis.readLine()
As I remember, this will try to read into a buffer until he founds a '\n'. But what if is never sent?
My ugly version breaks any design pattern and other recommendations, but always works:
int bytesExpected = clientSocket.available(); //it is waiting here
int[] buffer = new int[bytesExpected];
int readCount = clientSocket.read(buffer);
You should add the verifications for error and interruptions handling too.
With webservices results this is what worked for me ( 2-10MB was the max result, what I have sent)
Here is my implementation
clientSocket = new Socket(config.serverAddress, config.portNumber);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while (clientSocket.isConnected()) {
data = in.readLine();
if (data != null) {
logger.debug("data: {}", data);
}
}
Hallo i an trying to send Firmware file to modem board thru telnet.
Here is my code:
Socket s = null;
try {
SocketAddress socketAddress = new InetSocketAddress(InetAddress.getByName(addr), 23);
s = new Socket();
s.connect(socketAddress, 1000);
InputStream inputStream = s.getInputStream();
OutputStream outputStream = s.getOutputStream();
outputStream.write( (login + "\n") .getBytes());
Thread.sleep(300);
outputStream.write( (password + "\n") .getBytes());
Thread.sleep(300);
outputStream.write(("swupdate" + "\n").getBytes());
Thread.sleep(300);
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path_frm_vdsl);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
// Read File Line By Line
while ((line = br.readLine()) != null) {
// Print the content on the console
line = br.readLine();
if (line == null) {
Thread.sleep(1000);
} else {
//System.out.println(line);
outputStream.write(line.getBytes());
Log.v("---", line.getBytes() + "" + consumeInput(500, inputStream));
//Log.v("Update_Modem","Updated " + consumeInput(500, inputStream));
//outputStream.write(line.getBytes());
Thread.sleep(10);
}
}
It simply logs in sends swupdate command and dumps firmware file to output. After first line of input i am having java.net.SocketException: Broken pipe
And i can not read all file at once, not enough memory exception. (3Mb)
You know telnet uses in-channel signalling? the data stream contains escaped command instructions. When you open a telnet connection, a whole slew of initial commands are passed back and forth, as the server and client determine each others capabilities and preferences.
You may well find your byte stream is corrupted, if you just take whatever you get turning up at the server. You will need to honour the telnet protocol, e.g. properly understand the byte stream you're receiving.
The line terminator in the Telnet protcol is \r\n.
But why would you want to read the whole file into memory? And why all the sleeps? And why are you skipping every second line? And what is consumeInput()?
Just read and write bytes.
Not sure how your receiving end wants the firmware, plain binary, hex encoded, base64 encoded?
Anyway, here is how you would send it in plain binary
Socket s = null;
try {
SocketAddress socketAddress = new InetSocketAddress(InetAddress.getByName(addr), 23);
s = new Socket();
s.connect(socketAddress, 1000);
InputStream inputStream = s.getInputStream();
OutputStream outputStream = s.getOutputStream();
outputStream.write((login + "\n").getBytes());
Thread.sleep(300);
outputStream.write((password + "\n").getBytes());
Thread.sleep(300);
outputStream.write(("swupdate" + "\n").getBytes());
Thread.sleep(300);
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path_frm_vdsl);
byte[] buffer = new byte[1024];
int fillSize;
// Read File chunk by chunk
while ((fillSize = fstream.read(buffer)) != -1) {
outputStream.write(buffer, 0, fillSize);
}
outputStream.close();
} finally {
s.close();
}
So, read the file in chunks until there is no more data (read returns -1) and write the chunk (read returns how much was actually read).