Read/write in simple client-server app in Java - java

I'm new with Java and I'm trying to learn threads and socket. So decide to make simple client-server application following official java tutorial. My idea is simple - server wait for connection, if appears, it makes new thread with new socket, input and output. Client side -> make connection; new thread with socket, input, output and stdIn (to read line and after that send it to the server). But something is wrong (don't have any idea why) with my code. The connection is established, there's no exceptions. Could someone explain why doesn't work and how to fix it? Also could you have any suggestions about the code (probably it's not with best practices and things like that):
Client side:
public class Client {
private BufferedReader reader;
private Socket sock;
private PrintWriter writer;
public static void main(String[] args) {
Client client = new Client();
client.go();
}
public void go() {
setUpNetworking();
}
private void setUpNetworking() {
try{
sock = new Socket("127.0.0.1", 5000);
System.out.println("Network established");
ServerThread serverThread= new ServerThread(sock);
serverThread.start();
System.out.println("Type your message: ");
} catch (IOException e) {
System.out.println("Problem with establishing the network: " + e);
}
}
class ServerThread extends Thread {
Socket socket;
PrintWriter out;
BufferedReader in;
BufferedReader stdIn;
ServerThread(Socket socket) {
this.socket = socket;
try{
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
}catch (IOException e) {
System.out.println("Problem with trying to read/write to server: " + e);
}
}
#Override
public void run() {
String fromServer;
String fromClient;
while(true){
try{
if((fromServer = in.readLine()) != null) System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null) out.println(fromClient);
}catch(Exception e) {
System.out.println("msg exception: " + e);
}
}
}
}
}
Server side:
public class Server {
//Run server until keepGoing = false
private boolean keepGoing = true;
public static void main(String[] args) {
Server server = new Server();
server.go();
}
public void go() {
try {
ServerSocket serverSocket = new ServerSocket(5000);
while(keepGoing) {
Socket clientSocket = serverSocket.accept();
ClientThread t = new ClientThread(clientSocket);
t.start();
}
} catch (IOException e) {
System.out.println("Problem with socket/network: " + e);
}
}
class ClientThread extends Thread {
Socket clientSocket;
PrintWriter out;
BufferedReader in;
ClientThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try{
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
System.out.println("Problem with creating in/out: " + e);
}
}
#Override
public void run() {
String message;
while(keepGoing) {
try{
message = in.readLine();
out.println(message);
System.out.println(message);
} catch (IOException e){
System.out.println("Exception while try to read line: " + e);
}
}
}
}
}
PS I've changed a bit the code - instead of made ClientThread Class, I made new runnable class and pass that variable to thread class. Inspired by this question: "implements Runnable" vs. "extends Thread".

I think the problem is that both server and client are waiting for any input. Server:
message = in.readLine();
Client:
if((fromServer = in.readLine()) != null)
System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null)
out.println(fromClient);
But the client code already blocks on the fromServer = in.readLine() part, so it never gets to read from standard in, and thus nothing will be sent out to the server.
You could move your attempt to read from standard in to the setUpNetworking method, right after the System.out.println("Type your message: ");. Build a loop there which you exit if the user types "exit" or "quit" or something like that:
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String read = "";
do {
read = stdIn.readLine();
System.out.println("Read from stdin: " + read);
serverThread.send(read);
}
while (!read.equals("exit"));
The ServerThread.send() method is simple:
void send(String string) {
System.out.println("Sending to server: " + string);
out.println(string);
}
However, to make it work, you either have to flush the stream manually after writing to out, or use the following constructor:
out = new PrintWriter(socket.getOutputStream(), true);
See the PrintWriter's JavaDoc: True means auto-flush on newline.
I tested this setup and it worked for me. I was able to send something from the client to the server.
However, this is only the first step. I would implement both reading and writing as separate threads, for both client and server. And there is no graceful shutdown of sockets implemenented yet. A more complete yet simple example can be found on Oracle.

Related

java - server not recieving messages from client (reader.readLine() == null ?)

so i've been making a simple chat, than has a server and a bunch of clients connected to them. On the client side i have class ConnectionManager to manage creating socket and such. Here is it's core method:
public class ConnectionManager {
private Socket socket;
private BufferedReader reader;
private PrintWriter writer;
public ConnectionManager(String URL, int port){
tryConnectToServer(URL, port);
}
public BufferedReader getReader() {
return reader;
}
public PrintWriter getWriter() {
return writer;
}
private void tryConnectToServer(String ip, int servSocket) {
try{
socket = new Socket(ip, servSocket);
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
}
catch (IOException ex){
System.out.println("Unable to connect to specified server. Code pink");
ex.printStackTrace();
}
}
Connection Manager object is a part of ChatGUI. ChatGUI's fields writer and reader are obtained and set from CM in order to pass writer along with ChatGUI's JTextField (msgInput) to SendButtonListener:
private void addSendButton() {
JButton sendButton = new JButton("Send");
sendButton.addActionListener(new SendButtonActionListener(writer, msgInput));
panel.add(sendButton);
panel.add(this.msgArea);
}
Then, actionPerformed method does:
public class SendButtonActionListener implements ActionListener{
private PrintWriter writer;
private JTextField msgInput;
public SendButtonActionListener(PrintWriter pr, JTextField mi){
writer = pr;
msgInput = mi;
}
public void actionPerformed(ActionEvent event){
writer.println(msgInput.getText());
System.out.println("Sending: " + msgInput.getText());
flushMessageInputField();
}
private void flushMessageInputField(){
msgInput.setText("");
}
}
On the server side on the other hand i've got this:
try{
this.servSocket = new ServerSocket(port);
System.out.println("Server socket established");
}
catch (IOException ex){
System.out.println("Unable to establish server socket. Code pink \n");
ex.printStackTrace();
}
And after the above comes this:
public void waitForClients(){
System.out.println("The gates has been opened...");
while (true){
try {
Socket client = servSocket.accept();
processClient(client);
}
catch (IOException ex){
ex.printStackTrace();
}
}
}
private void processClient(Socket client){
writers.add(getClientWriter(client));
startUpdateFrom(client);
System.out.println("New client connected: " + client.getPort());
}
private PrintWriter getClientWriter(Socket client){
try{
return new PrintWriter(client.getOutputStream());
}
catch (Exception ex){
ex.printStackTrace();
}
return null;
}
And finally, a new thread starts to listen to any new messages from that client:
private void startUpdateFrom(Socket client){
new Thread(
new WaitAndSendToAllFrom(client))
.start();
}
Which is:
public class WaitAndSendToAllFrom implements Runnable{
BufferedReader reader;
public WaitAndSendToAllFrom(Socket clientSocket){
try{
reader = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
}
catch (IOException ex){
ex.printStackTrace();
}
}
public void run(){
try{
String message;
System.out.println("Thread: waiting for messages to send...");
while (true){
message = reader.readLine();
while (message != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}
}
}
catch (IOException ex){
ex.printStackTrace();
}
}
private void sendToAll(String message){
List<PrintWriter> writers = ServerClientConnector.getWriters();
for (PrintWriter pr : writers){
pr.println(message + "\n");
pr.flush();
}
}
}
The cycle gets to the "Thread: waiting for messages to send...", but not any further, reader.readLine() returns null (checked with a sysout :) ). I was trying to debug it, but i'm not so experienced in programing so much, especially debugging two separate codes working with each other. I've been looking at this for 3 days, and i'm seriously stuck here.
while (true){
message = reader.readLine();
while (message != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}
}
This makes no sense. You read one line and then keep testing. It for null in a loop in which it can never change.
A proper way to write this is:
while ((message = reader.readLine()) != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}

How to read input from a socket using threads JAVA

I am writing a simple socket programming application that uses a server and one client. I am trying to start a thread (from client file) that reads input from the socket input stream so that i can write messages to the server and read them back and print them to the screen at the same time. However, when i run my code, my code gets stuck at
message = in.readLine();
in InputReader.java file and reads no input?
My code is as follows, please help.
SimpleServer1.java
public class SimpleServer1 {
public static void main(String args[]){
int portNumber = Integer.parseInt(args[0]);
ServerSocket serverSocket = null;
Socket clientConnection = null;
try{
//setup sockets
serverSocket = new ServerSocket(portNumber);
clientConnection = serverSocket.accept();
System.out.println("Connected to" + clientConnection.getInetAddress());
//setup streams
BufferedReader in = new BufferedReader(new InputStreamReader(clientConnection.getInputStream()));
PrintWriter out = new PrintWriter(clientConnection.getOutputStream());
out.flush();
//read input from stream
String message;
while((message = in.readLine()) != null){
//return message to client
out.println("Echo: " + message);
System.out.println(clientConnection.getInetAddress() + ": " + message);
if (message.equalsIgnoreCase("bye")){
System.out.println("Closing connection...");
break;
}
}
//close streams
out.close();
in.close();
clientConnection.close();
}catch(Exception e){
e.printStackTrace();
}
}
SimpleClient1.java
public class SimpleClient1{
public static void main(String args[]){
String hostName = (args[0]);
int portNumber = Integer.parseInt(args[1]);
try{
Socket serverConnection = new Socket(hostName, portNumber);
PrintWriter out = new PrintWriter(serverConnection.getOutputStream(), true);
out.flush();
Thread listener = new Thread(new InputReader(serverConnection));
listener.start();
Scanner keyboard = new Scanner(System.in);
String userInput;
while((userInput = keyboard.nextLine()) != null){
out.println(userInput);
if (userInput.equalsIgnoreCase("bye")){
break;
}
}
//closing streams
out.close();
serverConnection.close();
}catch(Exception e){
e.printStackTrace();
}
}
InputReader.java <-- what i am trying to run my thread with
public class InputReader implements Runnable{
private Socket serverConnection;
private BufferedReader in;
public InputReader(Socket socket){
serverConnection = socket;
try{
in = new BufferedReader(new InputStreamReader(serverConnection.getInputStream()));
}catch(IOException ioE){ioE.printStackTrace();}
}
#Override
public void run() {
try{
String message;
while(true){
System.out.println("done");
message = in.readLine();
System.out.println(message);
}
}catch(IOException ioE){ioE.printStackTrace();}
}
Ultimately, I would like to both read and write from the socket streams using threads.
Thanks in advance :)
Cobezz
I believe you have to flush the stream you are writing to after you have written to it. You appear to flush the stream as soon as you create it, which won't have any effect.
in SimpleServer1.java you must be add out.flush();
while ((message = in.readLine()) != null) {
out.println("Echo: " + message);
out.flush();
System.out.println(clientConnection.getInetAddress() + ": " + message);
if (message.equalsIgnoreCase("bye")){
System.out.println("Closing connection...");
break;
}
}

Facing exception on closing client in Java

I am new to socket programming in java so facing a problem seems not difficult but unable to solve due to unfamiliarity. Following are codes for Client and Server.
Server Code:
public class connectionServer {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
String clientSentence;
String capitalizedSentence;
BufferedReader inFromClient;
DataOutputStream outToClient;
BufferedReader inFromUser;
try {
ServerSocket welcomeSocket = new ServerSocket(70);
Socket connectionSocket;
connectionSocket = welcomeSocket.accept();
System.out.println("Connection accepted for " + connectionSocket.getInetAddress() + ": " + connectionSocket.getPort());
InputStreamReader input = new InputStreamReader(connectionSocket.getInputStream());
inFromClient = new BufferedReader(input);
while (true)
{
if(input.ready())
{
clientSentence = inFromClient.readLine();
System.out.println(clientSentence);
}
String tempString = "FROM SERVER: What's problem......";
try
{
Thread.currentThread().sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
outToClient = new DataOutputStream(connectionSocket.getOutputStream());
if(outToClient != null)
{
outToClient.writeBytes(tempString + "\n");
outToClient.flush();
}
}
}
catch (IOException e)
{
System.out.println(e);
e.printStackTrace();
}
}
}
Client Code:
public class connectionClient {
static Socket clientSocket = null;
//////////////////////////////////////////
//////////////////////////////////////////
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
String sentence;
String modifiedSentence;
attachShutDownHook();
try
{
clientSocket = new Socket("127.0.0.1", 70);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());;
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes("FROM CLIENT 2: Hello \n\n");
while(clientSocket.isConnected())
{
sentence = "Please reply me....";
try
{
Thread.currentThread().sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
if(inFromServer.ready())
{
modifiedSentence = inFromServer.readLine();
System.out.println(modifiedSentence);
}
outToServer.writeBytes("FROM CLIENT 2:" + sentence + "\n");
outToServer.flush();
}
}
catch(IOException e)
{
System.out.println(e);
}
finally
{
System.exit (0) ;
}
}
}
When I stop the client following exception is thrown on server side
java.net.SocketException: Connection reset by peer: socket write error
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:132)
at java.io.DataOutputStream.writeBytes(DataOutputStream.java:276)
at connectionserver.connectionServer.main(connectionServer.java:57)
Any help in this regard will be highly appreciated. Thanks
This usually means you have written to an connection that had already been closed by the peer. In other words, an application protocol error.
Your code needs work.
Don't use ready(): just block in read() until data arrives. At present you're smoking the CPU while ready() returns false. This is probably causing the error.
isConnected() is always true after you connect the socket. It won't magically return false when the peer closes his end. You have to detected that via EOS or an exception. Looping on while (isConnnected()) isn't valid.
Don't mix streams and readers and writers. You're using a BufferedInputStream: use a BufferedWriter at the other end.

java sockets client sends to server but fails to listen

I have to do a very simple TCP server that listens to some client using TCP and returns the message in upper case.
The connection stablishes fine, the client sends messages perfectly and the server listens to them but the server won't answer and I don't have a clue of why is this happening...
Server:
//imports and stuff you don't really care about
public class ServerThread extends Thread {
private final Socket clientSocket;
private final Main controller;
private final Server server;
BufferedReader in;
PrintWriter out;
//constructor
ServerThread(Socket clientSocket, Main controller, Server server) throws IOException {
this.clientSocket = clientSocket;
this.controller = controller;
this.server = server;
//make input and output streams
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//THIS MAY BE WRONG
out = new PrintWriter(clientSocket.getOutputStream());
}
#Override
public void run() {
controller.out("Connected: " + clientSocket.getInetAddress().toString());
out.println("test");
try {
String msg;
while ((msg = in.readLine()) != null) {
//Prints this line
System.out.println(clientSocket.getInetAddress().toString() + " says: " + msg);
//THIS MAY BE WRONG
out.println(msg.toUpperCase());
System.out.println("Answered");//this line too
}
}catch(SocketException ex){
destroyMe();
}
catch (IOException ex) {
Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
destroyMe();
}
}
//couple of methods that don't interfere here
}
Client:
public class Client extends Thread {
private final String host = "localhost";
private final int port = 44444;
private final PrintWriter out;
private final Socket socket;
BufferedReader in;
private Main c;
public Client(Main c) throws IOException {
this.c = c;
socket = new Socket(host, port);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Connection Opened.");
}
public void send(String str) {
out.println(str); //this works fine
}
#Override
public void run() {
String msg;
while (true) {
try {
//THIS MAY BE WRONG but I don't think so
while ((msg = in.readLine()) != null) {
System.out.println("received: " + msg); //this never happens
c.out(msg);
}
//this line is always reached until I close the connection.
} catch (SocketException ex) {
System.out.println("Connection closed"); //this line is reached too
break;
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
//This works fine
}
}
}//end of the thread
//there are a couple of methods here but they don't do anything related
}
I don't see anything wrong but something must be.
Thanks for your help.
You are using a PrinterWriter to control the output of your Server code.
You are creating it without automatic flushing turned on via out = new PrintWriter(clientSocket.getOutputStream()); Automatic flushing when turned on, per the documentation, will occur when you write a message via the println, printf, or format methods.
Either turn on automatic flushing & use the above methods to write you message, call the flush method when you want to send a message, or use a different method altogether to control your Server output stream.
http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html

Simple Networking; Threads issue

I'm trying to make a simple client-server networking program. Initially, I was not running the Server and Client objects concurrently. The command prompt would just get stuck on trying to run the program. I then decided to use threads. The result is the same; I believe I have to use wait() and notify() somewhere but I'm not able to get it.
The Server needs to run first, but it will have to wait for the incoming Socket reference before it can proceed. I believe some lines need to be shifted here and there before a wait-and-notify mechanism is implemented. Here's my code so far -:
package networking;
import java.net.*;
import java.io.*;
import java.util.Scanner;
class Server implements Runnable
{
ServerSocket ss;
Socket incoming;
public void run()
{
try
{
ss = new ServerSocket(8189);
incoming = ss.accept();
OutputStream outs = incoming.getOutputStream();
InputStream ins = incoming.getInputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
out.println("Hello, Bye to exit");
out.println("This is the server program");
out.println("It will echo client stuff");
boolean done = false;
while(!done && in.hasNextLine())
{
out.println("Echo: " + in.nextLine());
if(in.nextLine().trim().equals("Bye"))
done = true;
}
incoming.close();
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
}
}
class Client implements Runnable
{
Socket s;
public void run()
{
try
{
s = new Socket("localhost", 8189);
InputStream ins = s.getInputStream();
OutputStream outs = s.getOutputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
while(in.hasNextLine())
System.out.println("Client: " + in.nextLine());
out.println("Bye");
s.close();
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
}
}
public class Networking
{
public static void main(String... args)
{
Thread server = new Thread(new Server());
Thread client = new Thread(new Client());
server.start();
client.start();
}
}
Any tips and pointers would be much appreciated; I just need a nod(or more) in the right direction.
Your code for opening serve and client is correct. But the problem is in the while loop for reading or writing data it falls in a deadlock. Because after establishing the connection booth server and client is waiting for each other to write something in the stream. Try with this.
class Server implements Runnable {
ServerSocket ss;
Socket incoming;
public void run() {
try {
System.out.println("Server STarted");
ss = new ServerSocket(8189);
incoming = ss.accept();
System.out.println("Client accepted");
OutputStream outs = incoming.getOutputStream();
InputStream ins = incoming.getInputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
out.println("Hello, Bye to exit");
out.println("This is the server program");
out.println("It will echo client stuff");
boolean done = false;
while (!done) { // && in.hasNextLine()
// out.println("Echo: " + in.nextLine());
// if (in.nextLine().trim().equals("Bye")) {
// done = true;
// }
out.println("TEsting from server");
}
incoming.close();
System.out.println("End server");
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
}

Categories

Resources