Read data from a Java Socket - java

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);
}
}

Related

How to send compressed data using UDP or TCP (lua / java)

I am making a server with lua clients and Java server.
I need some data to be compressed in order to reduce the data flow.
In order to do this I use LibDeflate for compressing the data on the client side
local config = {level = 1}
local compressed = LibDeflate:CompressDeflate(data, config)
UDP.send("21107"..compressed..serverVehicleID) -- Send data
On the server I use this to receive the packet (TCP)
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new
InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
String inputLine;
while ((inputLine = in.readLine()) != null) { // Wait for data
Log.debug(inputLine); // It is what get printed in the exemple
String[] processedInput = processInput(inputLine);
onDataReceived(processedInput);
}
I already tried sending it using UDP and TCP, the problem is the same.
I tried using LibDeflate:CompressDeflate and LibDeflate:CompressZlib
I tried tweaking the config
Nothing works :/
I expect to receive one packet with the whole string
But I received few packets each of them contains compressed characters. exemple (each line is the server think that he receive a new packet):
(source: noelshack.com)
After a lot of research I finnaly managed to fix my problem !
I used this :
DataInputStream in = new DataInputStream(new BufferedInputStream(clientSocket.getInputStream()));
int count;
byte[] buffer = new byte[8192]; // or 4096, or more
while ((count = in.read(buffer)) > 0) {
String data = new String(buffer, 0, count);
Do something...
}
I still haven't tested to see if the received compressed string works, I'll update my post when I try out.
EDIT: It seems to work
The only problem now is that I don't know what to do when the packet is bigger than the buffer size.
I want to have something that work in every situation and since some packet are bigger than 8192 they are just cut in half.
Assuming that the client side sends a single compressed "document", your server-side code should look something like this (TCP version):
is = new DeflaterInputStream(clientSocket.getInputStream());
in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String inputLine;
while ((inputLine = in.readLine()) != null) {
...
}
The above is untested, and also needs exception handling and code to ensure that the streams always get closed.
The trick is that your input pipeline needs to decompress the data stream before you attempt to read / process it as lines of text.

Socket Println never sending data

I have code on an android (Xamarin) device as such:
socket = new Socket();
socket.Connect(new InetSocketAddress(IP_ADDR, PORT));
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.InputStream));
PrintWriter writer = new PrintWriter(socket.OutputStream, true);
string userInput = "";
while ((userInput = reader.ReadLine()) != null)
{
writer.Println(userInput);
}
The server side is a Windows server. I am reading data fine. But Println is never sending the data. I have tried .Flush() afterward, to no avail. I even considered possible newline differences and changed the code to just .Print() with 13 and 10 after, then a flush. Still nothing. Any thoughts? TIA
Moments later, I discovered the answer.
Instead of 13, 10, I send the char representation, ala:
writer.Print(userInput);
writer.Print('\r');
writer.Print('\n');
writer.Flush();

Java TCP socket blocks at readLine

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".

readLine() never stops reading

inFromClientR.readLine() never stops. any ideas? Am I forgetting something?
Server:
/*{ some code:
send a file with a dataoutputstream to client using a new port(4000) and when transfer is done i want a responce message (e.g. OK) send back to server in the old port(6000)
}*/
ServerSocket listenTransferSocket = new ServerSocket(6000);
Socket connectionTransferSocket = listenTransferSocket.accept();
BufferedReader inFromClientR =
new BufferedReader(new InputStreamReader(connectionTransferSocket.getInputStream()));
System.out.println("Client's response to Transfer: " +inFromClientR.readLine());
Client:
/*{ some code:
receive the file on port (4000) and then the responce is sent to server using the following commands
}*/
Socket fileTransferSocket = new Socket("localhost", 6000);
DataOutputStream outToServerR =
new DataOutputStream(fileTransferSocket.getOutputStream());
outToServerR.writeBytes("Transfer completed " +'\n');
BufferedReader#readLine() tries to fill its buffer with 8192 bytes, regradless of any linefeeds it find meanwhile. Since you have the connection open, the receiving side will wait until 1) you have sent 8192 bytes, or 2) closes the connection.
You would be better off using some other framing mechanism, maybe an ObjectOutputStream/ObjectInputStream.
String line = null;
while ((line = inFromClientR.readLine()) != null) {
// do sth
}

C++ Client and Java Server

I did a Java Socket server, and a C++ Client.
However, the client connects to the server, without problems.
But when I write something client-server, the server doesn't catch the message.
What I'm doing wrong?
A little bit of the code of the Java Server:
DataInputStream dis=new DataInputStream(usrSocket.getInputStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
int data;
while((data = dis.read())>=0) {
out.write(data);
}
byte[] bytes = out.toByteArray();
String decrypt = new String(bytes);
if(decrypt.equals("status")){
System.out.println("Status emitted.");
}
System.out.println("Received a message.");
C++ Client writing:
QByteArray qba;
qba.append(text);
sock->write(qba.data());
qDebug() << "Send status";
I need help with that, thank you very much.
(that variable "text" it's a QString)
EDIT
Java server: That's only one part of all the code, the main thread waits for connections (Socket sock = server.accept()) and create a new thread for each user.
The code that I published of the java server, its one part of that threads for the users.
If you need ALL the code, plese tell me.
I will be waiting the answers!
Thank u very much!
Sorry if I answer ya late.
Try this code for Java Server.
ServerSocket ss = new ServerSocket(Port_No);
Socket incomingClient = ss.accept();
InputStream i = incomingClient.getInputStream();
OutputStream o = incomingClient.getOutputStream(); // Use it write to the Client Socket
InputStreamReader isr = new InputStreamReader(i);
BufferedReader br = new BufferedReader(isr);
String str = new String();
while ((str = br.readLine())!=null){
// do what you want with the data received in str.
}
As youre using QTcpSocket, it highly likely that you are running the client in the default asynchronous mode. This means after when you write after calling connectToHost, nothing will be sent as the socket is not connected.
Try using:
socket->connectToHost(hostAddress, hostPort, QIODevice::ReadWrite);
if (socket->waitForConnected()) {
QString text = "test string";
QByteArray array;
array.append(string);
qDebug() << socket->write(array);
} else {
// connect error!
}
Your Java code reads the socket until EOS and then prints something, which by the way is not a decryption operation. Your C++ client writes something and never closes the socket. So the server can never get out of the read loop.
If I read it correctly it is caused by the fact that your client is still running. Read() returns number >= 0 until the client socket is closed.

Categories