BufferedReader.readline() not working when chatting on socket - java

I'm using sockets to chat as part of a large application, however so you can read it easier i have made 2 classes that show the problem. I have a server and a client, the server opens a socket and waits for a client to connect once connected it sends them a welcome message. On the client side they display the welcome message then enter a loop to write to the PrintWriter. On the server side it will now enter a loop that constantly displays text from the bufferedReader however nothing is printing out, not sure if i'm being stupid but think it needs a fresh pair of eyes, Thanks.
public class Server {
public static boolean running = true;
public static PrintWriter out;
public static BufferedReader in;
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(1932);
while (true) {
Socket cs = s.accept();
out = new PrintWriter(cs.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(cs.getInputStream()));
out.println("Welcome");
out.flush();
while (running == true) {
String input = in.readLine();
if (input.equals("QUIT")) {
System.out.println("theyve gone :( ");
cs.close();
running = false;
} else {
System.out.println(input);
}
}
}
}
}
public class Client {
public static boolean running = true;
public static PrintWriter out;
public static BufferedReader in;
public static Scanner scan;
public static void main (String [] args) throws IOException{
Socket so = new Socket("localhost", 1932);
out = new PrintWriter(so.getOutputStream());
in = new BufferedReader(new InputStreamReader(so.getInputStream()));
System.out.println("TYPE QUIT TO LEAVE ");
System.out.println(in.readLine());
while(true){
scan = new Scanner(System.in);
String message = scan.next();
out.print(message);
out.flush();
}
}
}

In the server, you're reading the next line:
String input = in.readLine();
So the server blocks until the end of line is reached (or the stream is closed).
And on the client, you never send any end of line:
out.print(message);

Related

How to give an automated response back when receiving a specific message from the client (Java, sockets)

I basically was trying to give a response back from my server if my client sends me the message "Hello mr server". However it doesn't.
Here is my code :
public class Server {
public static final int PORT = 6666;
public static void main(String[] args) throws IOException {
new Server().runServer();
}
public void runServer() throws IOException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up and ready for connections.....");
while (true) {
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //for fetching data
String str = br.readLine(); //for fetching data
System.out.println("Client Data:" + str + '\n');
String dataSendingToClient = "gg";
OutputStreamWriter os = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out = new PrintWriter(os); //for sending data
out.println(dataSendingToClient);
os.flush();
if (br.equals("hey mr server")){
OutputStreamWriter os2 = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out2 = new PrintWriter(os); //for sending data
out2.println("hey mr client");
os.flush();
}
}
}
}
You are using br.equals("hey mr server") which will always return false, since br is not a String, but a BufferedReader
Instead you should use your already defined str variable str.equals("hey mr server")
Also note that with your current code, your server will only read one message from the client before moving on to the next connection
If you want your server to read more messages from a single client, you will need to loop until the client sends a disconnect message/the socket closes
while(true)
{
Socket socket = serverSocket.accept();
BufferedReader br = [...];
PrintWriter out = [...];
for(String message = br.readLine(); message != null; message = br.readLine())
{
//do stuff
//message is each line from the client
}
}
If you have multiple clients trying to connect, you will need to multithread the connections
I would recommend a class to enclose the connection details and use Stacks to poll if the client sent data
public static void main(String[] args) //or whatever other method you're running in
{
List<Connection> clients = new ArrayList<Connection>(); //some data structure to hold the clients
//start accepting connections
new Thread(new Runnable()
{
public void run()
{
while(true)
Connection client = new Connection(serverSocket.accept());
}
}).start();
//do something with the clients, read/write/whatever
}
private class Connection extends Runnable
{
private BufferedReader reader;
private PrintWriter writer;
private Queue<String> messages;
public Connection(Socket s)
{
reader = [...];
writer = [...];
messages = new LinkedList<String>();
}
public void run()
{
//just keep reading
while(true)
messages.add(reader.readLine();
}
public String read()
{
messages.poll();
}
public void write(String msg)
{
writer.write(msg);
writer.flush();
}
}
Note: take that as rough pseudocode

Java socket help debugging

I wrote a simple socket program but the sever is not printing out anything.
Client:
public class ChatClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 9001);
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
Scanner reader = new Scanner(System.in);
while (true) {
String test = reader.next();
out.write(test);
System.out.println(test);
//String line = in.readLine();
}
}
}
Server:
public class ServerApplication {
private static final int PORT = 9001;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
public static void main(String[] args) throws Exception {
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
System.out.println("Server starts!");
new ChatThread(listener.accept()).start();
}
} finally {
}
}
}
public class ChatThread extends Thread{
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public ChatThread(Socket socket){
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("Thread Starts!");
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
while(true){
System.out.println("Getting input!");
String input = in.readLine();
System.out.println("test");
if (input!=null){
//out.print(input);
System.out.println(input);}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Any ideas how should I fix this so when I type "Hello" on client, server will print out "Hello" using system.out.println()?
This is highly likely the socket buffers not being flushed and the data is not actually sent to the socket; the server is waiting for more data before sending a chunk.
If we look at the docs for PrintWriter:
... if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked ...
However, you are using print, not println, so the flushing is not automagic.
Try manualy flushing you streams after writing data:
out.write(test);
out.flush();
yep, this was an answer to a 3 year old post... question was edited and popped up on my stream
Testing your server using telnet (telnet localhost 9001) revealed that it's working just fine. I assume that the fact that it can only print a line at a time, rather than individual characters, is intended behavior.
I did find one bug. When terminating the telnet connection, the server would go into an infinite loop. I suggest the following change:
if (input!=null){
System.out.println(input);}
}
else {
break;
}
For the client, I was able to fix it simply by replacing write with println:
out.println(test);

java: closing client socket resets server socket

I have a very simple capitalization Java program. Client sends text read from standard input to server which converts that text into capital letters. Program works well but once client is stopped (NetBeans ide used), server is also reset. Server socket should keep listening for new connection from clients regardless of a client being stopped.
public class Client
{
public static void main(String[] args) throws IOException
{
try(Socket s=new Socket("localhost",9090))
{
while(true)
{
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
BufferedReader rd=new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedReader from=new BufferedReader(new InputStreamReader(System.in));
String read=from.readLine();
out.println(read);
String answer;
answer=rd.readLine();
System.out.println(answer);
}
}
}
}
public class Server
{
public static void main(String[] args) throws IOException
{
try(ServerSocket listener = new ServerSocket(9090);
Socket socket = listener.accept();)
{
while (true)
{
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Started...");
String transform=br.readLine();
String newStr=transform.toUpperCase();
out.println(newStr);
}
}
}
}
What happens is a normal behaviour. You server code only includes handling of a single client. The listener.accept() function only accepts latest connection to server. You need to put the listened.accept() in loop and handle all the exceptions that are raised within. The server-side code should look like this:
public class Server
{
public static void main(String[] args) throws IOException
{
try(ServerSocket listener = new ServerSocket(9090);
while (true) {
try {
Socket socket = listener.accept();)
…
} catch (SocketException ex) {
...
}
}
}
}
But keep in mind that this code will only handle single client at a time. No multi-threading in this code.
Your Server is closing the connection and then finishing becuase it is created outside the while loop. I believe this is what you need.
public class Server {
public static void main (final String[] args)
throws IOException {
while (true) {
try (ServerSocket listener = new ServerSocket(9090); Socket socket = listener.accept();) {
while (true) {
final BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
final PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Started...");
final String transform = br.readLine();
if (transform == null)
break;
final String newStr = transform.toUpperCase();
out.println(newStr);
}
}
}
}
}

NumberFormatException(Throwable) error when attempting to connect to a socket

I wrote a program which needs to connect to multiple server sockets. Each time it connects to a server, I try to save the server's InetAddress and localPort as an ArrayList in an ArrayList (connectedServers). So connectedServers is an ArrayList of ArrayLists. Before a new connection to a server is made, I try to check whether the same server is already connected with this client by checking through connectedServers.
While debugging in eclipse, the debugger stops at the line marked "ERROR" in the below code. In eclipse a new tab opens with the heading NumberFormatException(Throwable).<init>(String) line: 197 which shows the message Source not found.
If I take the marked line of code outside the if block, the connection gets made successfully. But I need it to work inside the if block. What can be the problem? The code is as follows.
public static ArrayList<ArrayList<Object>> connectedServers = new ArrayList<ArrayList<Object>>();
public static void main (String args[]) throws IOException {
listeningPort = 1111;
String host = takeInput("Host");
int port = takeInputInt("Port");
Socket a = connectToServer(host, port);
if (a != null) {
//....
}
//....
}
public static String takeInput(String inputName) throws IOException {
System.out.print(inputName+": ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
return input;
}
public static int takeInputInt(String inputName) throws IOException {
System.out.print(inputName+": ");
Scanner inputInt = new Scanner(System.in);
int input = inputInt.nextInt();
return input;
}
public static Socket connectToServer(String host, int port) throws IOException {
ArrayList<Object> element = new ArrayList<>();
element.add(host);
element.add(port);
//println(connectedServers);
//println(element);
//println(connectedServers);
if (connectedServers.contains(element) != true) {
//println(host + " " + port);
Socket fellowServer = new Socket(host, port);//<-------ERROR!!
connectedServers.add(element);
element.remove(host);
element.remove(0);
return fellowServer;
}
else{
return null;
}
}
Something could be wrong in here with input
Scanner inputInt = new Scanner(System.in);
int input = inputInt.nextInt();

Cannot communicate back to server from client

Here is my Server class, along with Admin/Client... The admin can recieve the initial message from the server, but cannot respond back to the server. The Server Socket is created, and when the admin connects to the Server, The Server's message is recieved and printed. Although once the Server's menu printout("1. Login, etc..."). I cannot enter an option via the console. It seems to be in a deadlock as soon as the admin prints out the menu sent from the server.
/**
A server that executes the Simple Bank Access Protocol.
*/
public class BankServer extends Thread {
private Socket sAdmin;
private Scanner inServer;
private PrintWriter outServer;
public static void main(String[] args) throws IOException {
Bank bank = new Bank(10);
ServerSocket server = new ServerSocket(8888);
System.out.println("Waiting for clients to connect...");
Thread admin = new BankServer();
admin.start();
while (true) {
Socket s = server.accept();
System.out.println("Client connected.");
BankService service = new BankService(s, bank);
Thread t = new Thread(service);
t.start();
}
}
#SuppressWarnings("resource")
public void run() {
try {
ServerSocket server = new ServerSocket(8889);
try {
System.out.println("Waiting for admin to connect...");
while (true) {
sAdmin = server.accept();
System.out.println("Admin connected.");
InputStream instream = sAdmin.getInputStream();
OutputStream outstream = sAdmin.getOutputStream();
inServer = new Scanner(instream);
outServer = new PrintWriter(outstream);
outServer.print(...+"1. Login\n"+etc...);
outServer.flush();
findCommand();
}
} finally {
sAdmin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void findCommand() throws IOException {
while (true) {
if (!inServer.hasNext()) {
return;
}
String command = inServer.next();
String chosenCommand;
switch (command) {
case "1":
chosenCommand = "LOGIN";
runCommand(chosenCommand);
break;
case "2":
etc...
}
}
}
...
}
Ive removed the runCommand method and some fields that don't cause problems to allow for an easier read.
Here is the the admin class. It will output the options sent from the server, but will not exit the loop of outputing the intial message, and allow me to enter a choice.
public class BankAdmin {
public static void main(String[] args) throws IOException {
Socket inAdmin = new Socket("localhost", 8889);
InputStream instream = inAdmin.getInputStream();
OutputStream outstream = inAdmin.getOutputStream();
Scanner in = new Scanner(instream);
PrintWriter adminOut = new PrintWriter(outstream);
Scanner console = new Scanner(System.in);
while (true) {
if (!in.hasNextLine()) {
String command = console.next();
System.out.println("Sending: " + command);
adminOut.print("command");
adminOut.flush();
} else {
String response = in.nextLine();
System.out.println(response);
}
}
}
}
This is what is happening:
After the server sends the menu to the client, the client becomes stuck in in.hasNextLine(). This is because the in.hasNextLine() will block (pause) for input, waiting for a new line (otherwise, it cannot determine whether there will be a next line). To fix this problem, you must use threads, with one waiting for input while the other reads from the console.
For more information, see the Javadoc on Scanner.hasNextLine()

Categories