Unexpected output in a basic networking client - java

import java.io.*;
import java.net.*;
public class BankClient {
public static void main(String[] args) throws IOException {
String host = "192.168.1.100";
int port = 7331;
try(
Socket bankSocket = new Socket(host, port);
PrintWriter out = new PrintWriter(bankSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(bankSocket.getInputStream()));
) {
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer;
boolean clientRunning = true;
while(clientRunning) {
System.out.println("TEST1");
while((fromServer = in.readLine()) != null) {
System.out.println(fromServer);
System.out.println("TEST2");
}
System.out.println("TEST3");
}
} catch (UnknownHostException e) {
System.err.println("Unknown host " + host);
System.exit(1);
} catch (IOException e) {
System.err.println("Disconnected");
System.exit(1);
}
}
}
So I'm just playing around with networking in Java and this is the script for a basic client, but for some reason I'm getting weird output when I run it with a server:
TEST1
Server Message 1
TEST2
Server Message 2
TEST2
The program is still running, but the output stops there. The thing that's confusing me is that TEST3 isn't being outputted continuously like I'd expect. It seems like the while((fromServer = in.readLine()) != null) breaks like it should after two iterations, but nothing after the while loop is running. The while(clientRunning) isn't breaking since the program is still running, but it also isn't iterating because TEST3 isn't being outputted. So what's happening here?

but it also isn't iterating because TEST3 isn't being outputted
Each time you call the in.readLine()) you are waiting for the server response to arrive.
Based on your result the server only passed 2 packets of data to the client thus giving you two results and will go back to read the next input stream of the server and will wait for response until the server is closed or when you add a socketTimeout in the Socket of the Client.

If you use while((fromServer = in.readLine()) != null) your program will wait for an input after it prints TEST2. Also, TEST3 is being outputted outside of the loop, so it will only output when the server stops sending messages, i.e., when (fromServer = in.readLine()) == null.
What about you changing this:
while((fromServer = in.readLine()) != null) {
System.out.println(fromServer);
System.out.println("TEST2");
}
To something like this:
while((fromServer = in.readLine()) != "EXIT") {
System.out.println(fromServer);
System.out.println("TEST2");
}
Then you can test your code using this test case:
TEST1
Server Message 1
TEST2
Server Message 2
TEST2
END
TEST3
Also, I highly recommend you to use java.util.Scanner to read streams.
Hope I could help.

Related

Java: cannot read from socket, thread gets stuck on readLine()

Here is my code for the server side:
#Override
public void run(){
String message;
String command;
String[] arguments;
try{
BufferedReader inStream = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
while(online){
message = inStream.readLine();
if(message == null)
continue;
if(message.charAt(0) == '/'){
int endOfCommandIndex = message.indexOf(' ');
command = message.substring(1, endOfCommandIndex);
arguments = message.substring(endOfCommandIndex + 1).split(" ");
if(command.equals("login")){
setUserName(arguments[0]);
setName(arguments[0]);
sendMessage(this, "Connected");
}
//....
}
}
}
As mentioned in the title, the thread gets stuck reading from the InputStream of the Socket (I checked with JDB and it's not a conditional waiting because it appears to be still "running").
I tried to write a line to the socket but it doesn't change its state at all. I'm trying to build a chat-like local application and I'm quite new to socket and streams. Thanks in advance.
For the client side:
String msg;
try{
while(!((msg = stdIn.readLine()).equals("/quit")))
toServer.println(msg);
}
catch(IOException e){
e.printStackTrace();
}
In case someone wants review my entire code, it is here hosted on github
It looks like the message is never flushed after being written into the socket stream.
Try either call:
toServer.flush();
after println, or enable auto flushing when constructing toServer:
toServer = new PrintWriter(socket.getOutputStream(), true);

wkhtmltopdf called from java getting hanged

We are the using the following code to generate PDFs using wkhtmltopdf
public class SystemUtils{
public String executeCommand(String... command) {
Process process = null;
try {
// Using redirectErrorStream as true. Otherwise we have to read both process.getInputStream() and
// process.getErrorStream() in order to not exhaust the stream buffer.
process = new ProcessBuilder(command).redirectErrorStream(true).start();
process.waitFor();
StringBuilder outputBuilder = new StringBuilder();
try(BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = stdError.readLine()) != null) {
outputBuilder.append(line).append(StringConstants.CARRIAGE_RETURN);
}
}
return outputBuilder.toString();
} catch (IOException | InterruptedException e) {
String exceptionMsg = "Error while executing command '"+command+"' : ";
LOGGER.error(exceptionMsg, e);
throw new AppException(exceptionMsg, e);
} finally {
if(process != null){
process.destroy();
}
}
}
public static void main(String[] args){
SystemUtils systemUtils = new SystemUtils();
String[] array = {"wkhtmltopdf", "/home/pgullapalli/Desktop/testsimilar1.html", "/home/pgullapalli/Desktop/test.pdf"};
systemUtils.executeCommand(array);
}
}
This works absolutely fine for smaller size files. But when we try to process a larger file, it is indefinitely waiting without any response. I am not sure what is going wrong? Can someone please suggest?
I moved process.waitFor() before the return statement and it started working. This probably could be happening as the output buffer has filled and we are not reading from it. After moving the process.waitFor after the stream reading, things are working fine.

How to properly stream data from a socket with Java

I am attempting stream data over a socket with Java in an attempt to write a Kafka producer. I've written a class to pull the data in but I'm not getting the results I'd expect. I've got it set up so the data is being streamed from a Linux box. The source of the data is a csv file that I'm using the nc utility to stream. The class is running on a Windows 10 machine from Eclipse. When I run the class I see two weird things.
The column headers don't get transmitted.
I can only run the class once. If I want to run it again, I have to stop nc and restart it.
Below is my code. Am I missing anything? At this point I'm just trying to connect to the socket and pull the data over.
I run nc with the following command:
$ nc -kl 9999 < uber_data.csv
Below is my class
import java.net.*;
import java.io.*;
public class Client
{
static String userInput;
public static void main(String [] args)
{
try
{
InetAddress serverAddress = InetAddress.getByName("servername");
Socket socket = new Socket(serverAddress, 9999);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((userInput = input.readLine()) != null) {
System.out.println(input.readLine());
}
input.close();
socket.close();
}
catch(UnknownHostException e1)
{
System.out.println("Unknown host exception " + e1.toString());
}
catch(IOException e2)
{
System.out.println("IOException " + e2.toString());
}
catch(IllegalArgumentException e3)
{
System.out.println("Illegal Argument Exception " + e3.toString());
}
catch(Exception e4)
{
System.out.println("Other exceptions " + e4.toString());
}
}
}
You're throwing away every odd-numbered line. It should be:
while ((userInput = input.readLine()) != null) {
System.out.println(userInput);
}
Secondly, you aren't closing the socket. Use a try-with-resources:
try
{
InetAddress serverAddress = InetAddress.getByName("servername");
try (
Socket socket = new Socket(serverAddress, 9999);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
while ((userInput = input.readLine()) != null) {
System.out.println(input.readLine());
}
}
}
catch (...)
First, each call readLine() tries to read line from input stream.
In userInput = input.readLine() you read header, but println(input.readLine()) read body and print in console.
while ((userInput = input.readLine()) != null) {
System.out.println(userInput); //instead input.readLine()
}
Second, I didn't use nc, but I think problem will solve if you will close socket (and reader) in finally statement.
I hope it would be helpful.
For the first question: you were trying to print userInput string. But it's printing the result of another readline() call.
For the second: after the file has been transferred, you have to stop and restart nc; no matter what you do from your side. It's from nc side.
See the nc documentation.

How to automatically update server and client side in java

I'm learning distributed systems basics and currently I'm trying to do a simple yet realistic messenger between one server and one client. What I do intend is that on each endpoint socket side (Server and Client) text automatically updates (like a real "messaging app"). In other words, I want that the moment I write and "send" the message, it automatically appears on recipient side. What I have now follows this schema:
I send a message (let's assume from client)
To see that message on Server's side I need to reply first (because Server's BufferedReader / Client's PrintWriter is only read after asking for the answer)
My code:
public class ClientSide {
public static void main(String [] args){
String host_name = args[0];
int port_number = Integer.parseInt(args[1]);
try {
Socket s = new Socket(host_name, port_number);
PrintWriter out =
new PrintWriter(s.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(s.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String answer;
while ((answer = stdIn.readLine()) != null) {
out.println(answer);
System.out.println("\nlocalhost said\n\t" + in.readLine());
}
} catch (IOException ex) {
Logger.getLogger(ClientSide.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class ServerSide {
public static void main(String [] args){
int port_number = Integer.parseInt(args[0]);
try {
ServerSocket ss = new ServerSocket(port_number);
Socket tcp = ss.accept();
PrintWriter out =
new PrintWriter(tcp.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(tcp.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String answer;
while ((answer = stdIn.readLine()) != null){
out.println(answer);
System.out.println("\nClient said\n\t" + in.readLine());
}
} catch (IOException ex) {
Logger.getLogger(ServerSide.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
How can I do this? Does it involve advanced knowledge on the matter?
Thanks in advance.
The core problem is that you want to wait for two events concurrently -- either a message from the socket, or input from the user!
You want to wait on both at the same time -- you don't want to be stuck waiting for a message in the socket if the user types a message; nor to be waiting for the user message while you have a new message from the network.
To 'wait' for messages from multiple streams, you have java.nio. I believe it is the most correct way of doing it.
But if you want to keep using the BufferedReader, there is a ready() method that returns true if and only if there is a message waiting to be read.
Your code after the in and stdIn declarations would then look something like (I didn't test it!!):
while(true) {
if(stdIn.ready()) {
System.out.println("I said " + stdIn.readLine());
}
if(in.ready()) (
System.out.println("He said " + in.readLine());
}
}
A few somewhat useful random links:
Java - Reading from a buffered reader (from a socket) is pausing the thread
Is there epoll equivalent in Java?

Running a basic web server

I have written a java class that implements basic web server.It gets the port number from console. This code is very basic, it returns what the client sends.Here are the code:
package p106;
import java.io.*;
import java.net.*;
public class HttpMirror {
public static void main(String[] args) {
try
{
int port = Integer.parseInt(args[0]);
ServerSocket ss = new ServerSocket(port);
for(;;)
{
Socket client = ss.accept();
BufferedReader in = new BufferedReader( new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream());
out.print("HTTP/1.0 200 en");
out.print("Content-Type text/plain");
String line;
while( (line = in.readLine()) != null)
{
if(line.length() == 0)
break;
out.print(line );
}
out.close();
in.close();
client.close();
} // Tekrar döngüye gir ve bir sonraki bağlantıyı bekle.
}catch(Exception e)
{
System.err.println(e);
}
}
}
I run this code and what must I write to my browser's address bar?
Thanks in advance.
Did you try localhost:port number here? Or 127.0.0.1:port number here?
For example, if the port number is 8050, then the address would be localhost:8050 or 127.0.0.1:8050
You don't specify the command you use to start your java engine.
int port = Integer.parseInt(args[0]);
indicates that the port is passed on the command line. So whatever port you pass there, you should put in your web browser.
Ex:
java HttpMirror 12345
http://localhost:12345
First you need to check the port and then http://localhost:Portnumber for example http://localhost:8050

Categories