Code running stuck at scanner.hasNextLine() - java

I try to make a little Server-Client connection.
They both have a Scanner and a PrintWriter, and they are writing to each other using a Socket's input and output stream.
Client.java:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
static ServerSocket serverSocket;
static Socket socket;
static PrintWriter printWriter;
static Scanner scanner;
public static void main(String[] args) throws UnknownHostException, IOException {
socket = new Socket("localhost", 13344);
scanner = new Scanner(socket.getInputStream());
printWriter = new PrintWriter(socket.getOutputStream());
printWriter.println("dataline 1");
printWriter.println("dataline 2");
printWriter.println("dataline 3");
printWriter.flush();
//Error!? => I never got the echo from server in output
while (scanner.hasNextLine()) {
String lineRead = scanner.nextLine();
System.out.println("From server" + lineRead);
}
socket.close();
scanner.close();
printWriter.close();
System.out.println("Client has quit.");
}
}
Server.java
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
static ServerSocket serverSocket;
static Socket socket;
static PrintWriter printWriter;
static Scanner scanner;
public static void main(String[] args) throws IOException {
serverSocket = new ServerSocket(13344);
System.out.println("Waiting for Client to connect");
socket = serverSocket.accept();
scanner = new Scanner(socket.getInputStream());
printWriter = new PrintWriter(socket.getOutputStream());
System.out.println("Client has connected!!");
while (scanner.hasNextLine()) {
String lineRead = scanner.nextLine();
System.out.println("From Client: " + lineRead);
}
//Error!? => This line never runs
System.out.println("Now sending echo to Client");
printWriter.println("Echo from server1");
printWriter.println("Echo from server2");
printWriter.flush();
socket.close();
printWriter.close();
scanner.close();
System.out.println("Server has quit.");
}
}
I start the server: java Server.java
I start the client: java Client.java
Server's output:
Waiting for client to connect
Client has connected!!
From Client: dataline 1
From Client: dataline 3
From Client: dataline 3
Client's output is empty, not a word on it.
As you can see Server's code termination stops AFTER it is read from Client's output stream, and Client's code termination stops BEFORE it could read from Server's output stream.
My question is:
How this Scanner-PrintWrier communication works, how do i know if a printWriter printed BEFORE a scanner could read in a server-client connection like this? What i did wrong and why? How to use properly a scanner?
E D I T:
#T.C Do you mean like this? Now i got full output, both Server and Client are quit after they are sent and received data.
I modified like this:
String line = "";
while (!line.equals("#")) {
line = scanner.nextLine();
if (!line.equals("#")) {
System.out.println("From server" + line);
}
}

The Scanner.hasNext*() methods will block to wait for input to scan, so you can't use it to detect when the client has finished sending.
Simplest way to solve this problem would be to have the client send a special string telling the server it's done sending.

I have already posted some samples on client-server communication with detailed description.
Please have a look at below post that might help you to understand it better.
Multiple clients access the server concurrently
Java Server with Multiclient communication.
Try with BufferedReader that contains ready() that tells whether this stream is ready to be read. A buffered character stream is ready if the buffer is not empty, or if the underlying character stream is ready.
You can try with InputStream#available() but it doesn't have read line method.
Go with the solution suggested by #T.C. but he is not provided any sample code on it. You can find in it my post.

Had almost the exact same problem, after banging my head in the keyboard for a couple of hours, this is what saved me:
printWriter = new PrintWriter(socket.getOutputStream(), true);
The second parameter sets auto-flushing to true.

Related

FileWriter only writes first line (Append Mode enabled, Java)

I have a problem with writing incoming information from a client to this program. The data comes in and there is output every second from the System.out, but the FileWriter only prints the first line of output from when the program was started. I stop the program manually, and check the file after. I'm unsure of what's wrong, please help.
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.net.*;
import java.io.*;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Server {
public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException {
String msg_received;
FileWriter fw = new FileWriter("HeartData.txt", true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter out = new PrintWriter(bw);
System.out.println("Waiting for Android client to connect...");
while (true)
{
try
{
ServerSocket server = new ServerSocket(2323);
Socket s = server.accept();
server.close();
InetAddress clientAddress = s.getInetAddress();
System.out.println("Incoming connection from: " + clientAddress.getHostName() + "[" + clientAddress.getHostAddress() + "]");
DataInputStream DIS = new DataInputStream(s.getInputStream());
msg_received = DIS.readUTF();
out.println(msg_received + "," + LocalTime.now() + "," + LocalDate.now());
System.out.printf("Android says: %sat %s%n", msg_received, LocalTime.now());
}
catch (IOException e){e.printStackTrace();}
finally {
out.close();
}
}
}
}
Example Output:
Waiting for Android client to connect...
Incoming connection from: hostname.domain[ipaddress]
Android says: SOMETHING
at 10:51:06.013
You have this structure:
while (true) {
try {
// Code which writes one line
} finallly {
out.close();
}
}
In other words, you're closing the output after the first line, but continuing to do work. That's not going to reopen the output...
You should really use a try-with-resource block for the whole thing, with the while loop entirely inside it, so that you don't close the writer until your whole loop has finished. (Admittedly at the moment it can only finish due to an exception... you might want to add some non-exceptional way of stopping the loop...)

ServerSocket receives no data in a loop

I use ServerSocket to get data from client in a while loop, it works at the first run, but fails after second round.
I did some search but still can't figure out what happened.
Server side code
package com.gorilla.main;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server2 {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(44444);
while(true){
System.out.println("another round");
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
System.out.println("available: "+ inputStream.available());
byte[] b = new byte[inputStream.available()];
inputStream.read(b);
System.out.println(new String(b));
System.out.println("=======================");
socket.close();
}
}
}
Clent side code
package com.gorilla.main;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client2 {
public static void main(String [] args) throws Exception{
Socket socket = new Socket("127.0.0.1", 44444);
String s = "Hello World";
byte [] b = s.getBytes();
socket.getOutputStream().write(b);;
socket.close();
}
}
and the output at Server side console after I ran client 3 times.
another round
available: 11
Hello World
=======================
another round
available: 0
=======================
another round
available: 0
=======================
another round
Any suggestion would be appreciated. Thanks.
You use InputStream.available() to size your buffer and that's not how one reads from a socket. You should allocate a buffer (usually sized statically, or maybe configurable) and read in a loop
// server code
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buffer)) > -1) {
// do something
}
The Javadoc of InputStream.available():
Returns an estimate of the number of bytes that can be read (or
skipped over) from this input stream without blocking by the next
invocation of a method for this input stream. The next invocation
might be the same thread or another thread. A single read or skip of
this many bytes will not block, but may read or skip fewer bytes.
If your protocol is text-based, you can wrap the socket's input stream inside a Scanner and thus the loop becomes
while (scanner.hasNextLine()) {
String line = scanner.next();
}

Can I have a program with 2 sockets in Java?

This is a simple chat program in Java. I know I can get the work done by 1 socket but I was wondering why not use 2 sockets?
This executes but does not work as intended. Kindly see the code and find the error. Please help me as i am new to this.
Server code is below.
Server.java
import java.io.*;
import java.net.*;
public class server {
public static void main(String[] args)throws IOException {
ServerSocket ss=new ServerSocket(10001);
Socket s=ss.accept();
Socket s1=new Socket("localhost",10005);
DataInputStream di=new DataInputStream(s.getInputStream());
DataOutputStream dot=new DataOutputStream(s.getOutputStream());
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String str1="",str="";
while(str1!="exit"){
str=(String)di.readUTF();
System.out.println("message="+str);
System.out.println("Enter message:");
str1=br.readLine();
dot.writeUTF(str1);
dot.flush();
}
di.close();
dot.close();
s1.close();
s.close();
ss.close();
}
}
Client code is below kindly tell the problem.
i know i can get the work done by 1 socket but i was trying why not use 2 sockets.
Client.java
import java.io.*;
import java.net.*;
public class client {
public static void main(String[] args) throws IOException{
ServerSocket ss;
ss = new ServerSocket(10005);
Socket s=ss.accept();
Socket s1=new Socket("localhost",10001);
DataInputStream di=new DataInputStream(s.getInputStream());
DataOutputStream dot=new DataOutputStream(s1.getOutputStream());
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String str="",str1="";
while(str1!="exit"){
System.out.println("Enter message:");
str1=br.readLine();
dot.writeUTF(str1);
dot.flush();
str=(String)di.readUTF();
System.out.println("message="+str);
}
dot.close();
di.close();
s1.close();
ss.close();
}
}
Yes, you can open (within reason) as many sockets as you want from a single JVM.
The problem with your code that you're using a blocking API, meaning that the thread doesn't return from the call br.readLine() and so it cannot do any more work (including waiting for data on other sockets).
You've got a couple of options:
create a thread per socket (being careful of resource limitations).
use the NIO API that is inherently non-blocking.
There are two problems you will need to fix to make your program work:
Both server and client passively open a socket first and then both wait for the other one to connect first (ss.accept()). Solution: In client.java, move the the line ss.accept() below the active open Socket s1=new Socket("localhost",10001);.
The server uses socket s for input and output. You probably want to use s1 as output. Solution: In server.java, in the line DataOutputStream dot=new DataOutputStream(s.getOutputStream());: replace s with s1.
Please let me know if the program now works as expected.
For your future experiments, you might want to have a look at this tutorial on NIO selectors or threaded network application models, as Nick Holt suggested.

Java TCP Echo Server - Broadcast

I have a simple echo server, and I want when a connected user types anything to the server, all other clients and that client will get a the message + " | MOD".
It wont send to all clients now but it should and I just don't know what's wrong in my code, so now it will just send the message + " | MOD" to the client who sent the message but not to all others also as it should.
I just don't get it, I have a loop that goes through all clients, but it still won't send to all.
SERVER:
package com.murplyx.server;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
public static ServerSocket server;
public static ArrayList<Socket> clients = new ArrayList<Socket>();
public static void broadcast(String message) {
try {
for (Socket socket : clients) {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(message);
}
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
try {
server = new ServerSocket(9000);
while (true) {
clients.add(server.accept());
for (Socket socket : clients) {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
if (line != null) {
broadcast(line + " | MOD");
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
CLIENT:
package com.murplyx.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String args[]) {
try {
while (true) {
Socket socket = new Socket("localhost", 9000);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
out.println(input.readLine());
System.out.println(in.readLine());
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Please help.
Thanks alot.
One of the issues you have is that each client will repeatedly do read stdin, write socket, read socket, write stdout, ... ad infinitum.
When you broadcast all other clients are still typically sat in the read stdin phase, so they don't know that there's stuff waiting to be read on the socket. They're still waiting for the user to enter something.
One of the simplest options is to start two threads in each client - one just handles read stdin, write socket, ... and the other handles read socket, write stdout.
[Another (potentially more sophisticated) option us to use Java NIO to poll both the socket and stdin for available input at the same time].
A second issue is that you're blocking in the accept call in the server, and then reading from each socket in turn. You might accept in one thread, and have another thread per client read from just the client, and rebroadcast to the others. NIO can also be a good option here - you can poll for reads any any client.
I'm not exactly sure how ArrayLists play with sockets, so I definitely would go back to using a normal array for it (see the edited code here Java EchoTCPServer - Send to all clients)
Some things I see that I think can to be fixed:
On the Client:
-Stop closing the socket in the While loop. Close it OUTSIDE the while loop (When the client is done with the server). Also, declare the socket outside the Loop.
NOTE ON THIS: When a client makes a socket to connect to the server, it is automatically given a device port, so two different devices will never have the same IP connected to the server. A TCP connection consists of 2 ports, server socket and client socket, and the sockets are denoted by [deviceip:port,serverip:port] (iirc).
-Also, on the client you don't need to declare a new reader everytime you move through the while loop. Put that all outside. The only thing inside the while loop should be your readline + print statements.
-readLine is a blocking method. (just in case you don't know what that means, it means that readLine will make your program be stuck there until the it actually reads a line. To bypass this, you can use an if statement combined with the .ready() function. The ready function checks to see if there is anything to be "read in", so if there's no input it wont be stuck on "readLine".
On the Server:
-Like i said earlier, I'd change back to using a normal Array.
-Your server will still get stuck on .accept(). As such, you will never be able to read input from the clients except once after each connection. You can use a thread to listen instead, and it will still work.
eg: (this code goes with the code that's in the link i attached (also your question), put it before the while loop of your server)
// create a tcp listener thread to deal with listening to clients
Thread listenerThread = new Thread() {
public void run() {
String clientSentence;
while (true) {
//loop through each connected socket
for (int i = 0; i <= intLastSocket; i++) {
Socket z = clientSocket[i];
//make sure the socket is not null or closed (can't do anything
//with closed or null sockets
if ((z != null) && (!z.isClosed())) {
try {
// Deal with TCP input here
BufferedReader input = new BufferedReader(new
InputStreamReader(z.getInputStream()));
// read in a line but only if there is one
if (input.ready()) {
clientSentence = input.readLine();
}
} catch (IOException x) {
printTCP("IOException caught when reading in: "
+ x.toString());
}
if (clientSentence != null) {
System.out.println("Received from client: "
+ clientSentence);
//send this message to the client
outputStream[i].println(clientSentence + " | MOD");
}
// clear the input
clientSentence = null;
}
}
}
}
};
listenerThread.start();

Java TCP server received every line from Client when all of them are sent

I wrote two small java programs: a TCP client which sends many lines of data from a txt file, and a TCP Server which accepts connection and receives line by line.
It works, but Server receives all the lines together, when transmission is over and client closes the socket. I don't understand why, because I'm using flush after each line sent into the Client, and I always thought that was to avoid this kind of situation.
If my test.txt file contents the numbers 1 2 3 ... 10, each one in a new line, Server's output is: "12345678910" and then in a new line it writes in console "null".
Server code:
import java.io.*;
import java.net.*;
class ServidorTCP {
private String HOST;
static final int PUERTO = 20001;
public ServidorTCP( ) {
try{
ServerSocket skServidor = new ServerSocket(PUERTO);
Socket skCliente = skServidor.accept();
DataInputStream inFromClient = new DataInputStream(new BufferedInputStream(skCliente.getInputStream()));
while(true){
String lineaLeida = inFromClient.readUTF();
if(lineaLeida.equals("END")) break;
System.out.println(lineaLeida);
}
inFromClient.close();
skCliente.close();
skServidor.close();
System.out.println( "Transmission ended" );
} catch( Exception e ) {
System.out.println( e.getMessage() );
}
}
public static void main( String[] arg ) {
new ServidorTCP();
}
}
Cliente code:
import java.io.*;
import java.net.*;
class ClienteTCP {
static final String HOST = "192.168.1.201";
static final int PUERTO = 20001;
public ClienteTCP( ) {
try{
Socket skCliente = new Socket(HOST, PUERTO);
if(skCliente.isConnected()) System.out.println("Connected!");
DataOutputStream outToServer = new DataOutputStream(skCliente.getOutputStream());
File testFile = new File("test.txt");
BufferedReader input = new BufferedReader(new FileReader(testFile));
String line;
while((line=input.readLine())!=null) {
if(!line.endsWith("\n")) line = line + "\n";
System.out.println("Sending: " + line);
outToServer.writeBytes(line);
outToServer.flush();
Thread.currentThread().sleep(1000);
}
outToServer.writeBytes("END");
input.close();
outToServer.close();
skCliente.close();
} catch( Exception e ) {
System.out.println( e.getMessage() );
}
}
public static void main( String[] arg ) {
new ClienteTCP();
}
}
Where is the problem?
EDIT: I have edited the code as suggested. Now doesn't receive anyhing
The fact of the matter is that your code doesn't work at all, let alone before or after the socket is closed. You are writing with writeUTF() and reading with readLine(). This does not work. You need to:
write with DataOutputStream.writeUTF() and read with DataInputStream.readUTF()
write with println() (supplied by several I/O classes), or write() or print() (supplied by several I/O classes), followed by BufferedWriter.newline(), or
write with ObjectOutputStream.writeObject() and read with ObjectInputStream.readObject().
Etc. Writing with one API and reading with a non-symmetrical API doesn't work.
The problem is not with reading or writing (or at least not explicitly). The problem is your string. input.readLine() removes the end of line which means the string you're sending is just the number. On the server side then you receive a lot of strings but inFromClient.readLine() waits until it gets an end of line which never arrives until the stream closes and sends an end of file.
Just add an end of line to every string you're sending and it should work.

Categories