Java Simple EchoServer won't work - java

I read through SO a lot and I found many examples which were doing what I am trying to do. But I just can't find the issue in my code at all. May be I just need a fresh set of eyes to look at my code.
So with risk of being flagged for duplicate thread here is goes. I have a simple Java code. It opens a port. Connects a socket to that. gets the inputstream and outputstream. Puts some text to output stream and inputstream tries to read the text. When the mehtod for readLine is executed it does not return back to the code. It just keeps running and never comes back to main method.
import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;
public class echoserver {
public static void main(String[] args) {
// TODO Auto-generated method stub
String hostName = "127.0.0.1";
// InetAddress.getLocalHost()
int portNumber = 5000;
ServerSocket ss = null;
Socket echoSocket = null;
try {
ss = new ServerSocket(portNumber);
echoSocket = new Socket(hostName, portNumber);
// echoSocket = ss.accept();
System.out.println("open");
System.out.println(echoSocket.isBound());
PrintWriter writer = new PrintWriter(echoSocket.getOutputStream());
for (int i = 0; i < 100; i++) {
writer.print("test String");
}
writer.flush();
// writer.close();
System.out.println("inputstream read");
DataInputStream is = new DataInputStream(echoSocket.getInputStream());
String fromStream = is.readLine();
System.out.println(fromStream);
System.out.println("bufferreader read");
BufferedReader reader = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
String fromReader = reader.readLine();
System.out.println(fromReader);
} catch (UnknownHostException ex1) {
// TODO Auto-generated catch block
System.out.println("EX1");
ex1.printStackTrace();
}
catch (IOException ex2) {
// TODO: handle exception
System.out.println("EX2");
ex2.printStackTrace();
}
finally {
try {
echoSocket.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
EDIT : Updated Code below... The only issue in this code is that while loop in Server.Run never ends. I looked for some other attributes (I remember something like isTextAvailable) but could not find it. The idea behind the code is to convert it into a chat client. needless to say its a struggle !
EDIT 2: I found the the issue. I never closed the socket from writer end so the listner kept on listening ! Thanks for help everyone !
clientsocket.close();
Added one line and it worked!
import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;
import java.util.*;
public class echoserver {
static echoserver echo;
public static class Client implements Runnable {
Socket clientsocket;
String hostName = "127.0.0.1";
int portNumber = 5000;
static int onesleep = 0;
public void run(){
System.out.println("Client Run " + new Date());
try {
clientsocket = new Socket(hostName,portNumber);
PrintWriter writer = new PrintWriter(clientsocket.getOutputStream());
for (int i = 0; i < 10; i++) {
writer.println("test String " + i );
}
writer.flush();
clientsocket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Server implements Runnable {
public void run(){
System.out.println("Server Run" + new Date());
int portNumber = 5000;
ServerSocket ss = null;
Socket serversocket = null;
InputStreamReader streamReader;
try {
ss = new ServerSocket(portNumber);
serversocket = ss.accept();
System.out.println("bufferreader read " + new Date());
streamReader = new InputStreamReader(serversocket.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
String fromReader;
System.out.println(reader.ready());
System.out.println(reader.readLine());
while ((fromReader = reader.readLine()) != null) {
System.out.println(fromReader);
}
System.out.println("After While in Server Run");
} catch (IOException ex_server) {
// TODO Auto-generated catch block
System.out.println("Server Run Error " + new Date());
ex_server.printStackTrace();
}
finally {
try {
serversocket.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("open" + new Date());
System.out.println(serversocket.isBound());
}
}
public void go(){
Server server = new Server();
Thread serverThread = new Thread(server);
serverThread.start();
Client client = new Client();
Thread clientThread = new Thread(client);
clientThread.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
echo = new echoserver();
echo.go();
}
}

I had prepared a version of this post earlier, but based on your last comment in the other answer, it seems you have already figured it out. I'll posting this anyways, in case it is of any help.
The broad answer is that your class, as you currently have it, effectively represents both the client-side AND server-side portions within the same thread / process. As you've seen, you're able to write your data to the outbound (or client-side) socket, but the server-side component never gets a chance to listen for incoming connections.
Consequently, when you attempt to read data from the inbound (or server-side) socket's input stream, nothing exists because nothing was received. The readline() method ultimately blocks until data is available, which is why your program seems to hold at that point. Additionally, like haifzhan said, creating a new socket using new Socket(...) doesn't establish the connection, all you have is a socket with nothing in the stream.
The ServerSocket#accept method what you need to use in order to listen for connections. This method will create the socket for you, from which you can attempt to read from its stream. Like haifzhan said, that method blocks until a connection is established, which is ultimately why it cannot function properly in a single-threaded environment.
To do this within the same application, you'll simply need to separate the components and run them in separate threads. Try something like the following:
public class EchoClient {
public static void main(String[] args) throws InterruptedException {
new Thread(new EchoServer()).start(); // start up the server thread
String hostName = "localhost";
int portNumber = 5000;
try {
Socket outboundSocket = new Socket(hostName, portNumber);
System.out.println("Echo client is about to send data to the server...");
PrintWriter writer = new PrintWriter(outboundSocket.getOutputStream());
for (int i = 0; i < 100; i++) {
writer.print("test String");
}
System.out.println("Data has been sent");
writer.flush();
outboundSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the server component, which operates as a separate thread:
public class EchoServer implements Runnable {
public void run(){
try {
ServerSocket ss = new ServerSocket(5000);
System.out.println("Waiting for connection...");
Socket inboundSocket = ss.accept();
System.out.println("inputstream read");
DataInputStream is = new DataInputStream(inboundSocket.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String fromStream = reader.readLine();
System.out.println(fromStream);
System.out.println("bufferreader read");
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

You did not connect to any client side socket...
From Writing the Server Side of a socket:
The accept method waits until a client starts up and requests a
connection on the host and port of this server. When a connection is
requested and successfully established, the accept method returns a
new Socket object which is bound to the same local port and has its
remote address and remote port set to that of the client. The server
can communicate with the client over this new Socket and continue to
listen for client connection requests on the original ServerSocket.
ss = new ServerSocket(portNumber);
echoSocket = new Socket(hostName, portNumber)
// echoSocket = ss.accept();
You should not use new Socket(host, port) to create a echoSocket, the ss.accept() is the correct way to establish the server client connection.
The reason it hangs because your code above(echoSocekt = ss.accept();) is not correct so the following will not be availalbe
DataInputStream is = new DataInputStream(echoSocket.getInputStream());
If you invoke is.available(), it will return 0 which means 0 bytes can be read from.
Read the link I provided, check EchoServer.java and EchoClient.java, and you will estiblish your own connection

Related

Why can't i run the client side of this simple server-client app more than once?

Here's the code for server side :
public class EchoServer {
public static void main(String[] args) {
int port = 8080;
try {
ServerSocket server = new ServerSocket(port);
Socket cliSocket = server.accept();
Scanner in = new Scanner(cliSocket.getInputStream());
PrintWriter write = new PrintWriter(cliSocket.getOutputStream(),true);
String message;
while((message=in.nextLine()) != null){
write.println(message+" added");
}
write.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and here's the client side :
public class EchoClient {
public static void main(String[] args) {
String ip = "localhost";
int port = 8080;
try {
Socket client = new Socket(ip, port);
PrintWriter write = new PrintWriter(client.getOutputStream(), true);
Scanner in = new Scanner(client.getInputStream());
Scanner read = new Scanner(System.in);
String input;
while((input=read.nextLine()) != null){
write.println(input);
System.out.println("sent by server:" + in.nextLine());
}
write.close();
in.close();
read.close();
client.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Now when I run the server and then the client, it works. But if close the client app, and i run it once again, the server won't allow connection.
What is the solution in situations like this?
Your server program only accepts one client connection and exits after handling the connection.
If you want it to repeatedly accept client connections, you need to use a loop around the code you have in main()
The easiest solution is that every time you accept a connection, you launch a new thread to handle the client. That would allow you to handle any number of clients, and also deal with general TCP issues like sockets that are stuck open when clients are killed.
Something like this:
public class EchoServer {
public static void main(String[] args) {
int port = 8080;
ServerSocket server = new ServerSocket(port);
while (true) {
//wait for next client to connect
Socket cliSocket = server.accept();
//hand off socket to another thread
MyHandler handler = new MyHandler(cliSocket);
Thread clientHandler = new Thread(handler);
clientHandler.start();
}
}
}
public class MyHandler implements Runnable {
public MyHandler(Socket cliSocket)
{
//store socket
}
#override
public void run()
{
while(true) {
//handle client comms
}
}
}

Java can't get client or server response

I'm from Poland, so I'm sorry for any mistakes.
I've coding for a while a small server and client connection, when I stopped on annoying problem. When I send from client to server information (String), server can get it, but can't respone to it.
Here it is code.
Client
private static Socket socket;
public static void main(String args[]){
try{
String host = "localhost";
int port = 25002;
InetAddress address = InetAddress.getByName(host);
socket = new Socket();
socket.connect(new InetSocketAddress(host, port), 5000);
//Send the message to the server
System.out.println("< "+sendMessage(socket));
//socket.shutdownOutput();
System.out.println("> "+getMessage(socket));
}catch (SocketTimeoutException e){
System.out.println(e.getMessage()); // changed
}catch (IOException e){
System.out.println(e.getMessage()); // changed
}catch (IllegalBlockingModeException e){
System.out.println(e.getMessage()); // changed
}catch(IllegalArgumentException e){
System.out.println(e.getMessage()); // changed
}finally{
//Closing the socket
try{
socket.close();
}catch(Exception e){
System.out.println(e.getMessage()); // changed
}
}
}
public static String sendMessage(Socket client){
try {
String message = "test";
PrintWriter writer = new PrintWriter(client.getOutputStream(), true);
writer = new PrintWriter(client.getOutputStream(), true);
writer.print(message);
writer.flush();
writer.close();
return message;
} catch (IOException e) {
System.out.println(e.getMessage()); // changed
return "false";
}
}
public static String getMessage(Socket client){
try {
BufferedReader socketReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
return socketReader.readLine();
} catch (IOException e){
System.out.println(e.getMessage()); // changed
return "false";
}
}
And.. server
public class kRcon{
private static Socket socket;
private static ServerSocket serverSocket;
private static Thread u;
private static class Server extends Thread {
public void run() {
int port = 25002;
try {
serverSocket = new ServerSocket(port);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(true) {
try {
socket = serverSocket.accept();
BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter socketWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String str = socketReader.readLine();
socketReader.close();
System.out.println(str);
socketWriter.write("test");
socketWriter.flush();
socketWriter.close();
}
}catch (IOException e1) {
e1.printStackTrace();
}
}
public static void init(){
try {
u = new Server();
u.setName("Server");
u.start();
} catch (IOException e) {
System.out.println(e.getMessage()); // changed
}
}
}
Results
If, I start server first all looks nice.
So, I start the client with parametr "test", nad output to console is:
< test
Socket is closed // changed
On server-side in console I have:
"test"
Socket is closed // changed
I tried to shutdown inputs and outputs and dosen't work.. I don't know to do now. Please help :c
Edited 2015-04-03
I've changed lines with comment "changed".
For Google, and readers
To fix problem, don't close StreamReaders nad StreamWriters on client's sides.
Thanks to EJP, for help!
Greetings from Poland.
When you get an exception, print it. Don't just throw away all that information. And don't return magic Strings either. In this case you should have let the exception propagate. If you had done all that you would have seen the exception SocketException: socket closed being thrown by getMessage(), and you would have had something concrete to investigate, instead of a complete mystery.
It is caused by closing the PrintWriter in sendMessage(). Closing either the input or output stream of a socket closes the other stream and the socket.

Java - client-server clock

I'm kind of stuck on one issue. I got a client-server app in Java, where multiple clients can connect to a server. Now I have a cyclic operation, which is getting the current time (corresponding to my ClockTask on the server side). But I don't really know how do I transmit this time data to all connected clients. It should be done somehow by ObjectOutputStream I guess, but it would be nice if someone could clue me in.
Here's my server code, together with thread running a client connection:
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listeningSocket = true;
try {
serverSocket = new ServerSocket(11111);
} catch (IOException e) {
System.err.println("Could not listen on port: 11111");
}
while(listeningSocket){
System.out.println("Waiting for a client to connect...");
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected!");
ConnectThread ct = new ConnectThread(clientSocket);
ct.start();
}
serverSocket.close();
}
}
Connect thread:
public class ConnectThread extends Thread{
private Socket socket = null;
public ConnectThread(Socket socket) {
super("ConnectThread");
this.socket = socket;
}
#Override
public void run(){
ObjectOutputStream serverOutputStream = null;
ObjectInputStream serverInputStream = null;
try {
System.out.println("check");
serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
System.out.println("check");
serverInputStream = new ObjectInputStream(socket.getInputStream());
serverOutputStream.writeInt(42);
System.out.println("check");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
serverOutputStream.close();
serverInputStream.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
and the client:
public class Client {
public static void main(String[] arg) {
Socket socketConnection = null;
ObjectOutputStream clientOutputStream = null;
ObjectInputStream clientInputStream = null;
try {
socketConnection = new Socket("127.0.0.1", 11111);
clientOutputStream = new ObjectOutputStream(
socketConnection.getOutputStream());
clientInputStream = new ObjectInputStream(
socketConnection.getInputStream());
System.out.println("check");
System.out.println(clientInputStream.readInt()); // HERE'S WHERE THE EXCEPTION OCCURS
} catch (Exception e) {
System.out.println("The following exception has occured and was caught:");
System.out.println(e);
}
finally{
try {
clientOutputStream.close();
clientInputStream.close();
socketConnection.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Clock task:
public class ClockTask extends TimerTask {
#Override
public void run() {
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Calendar c = Calendar.getInstance();
System.out.println(dateFormat.format(c.getTime()));
//some object output stream here??
}
}
I don't suggest sending a Calendar object as it is a very expensive object using around 2900 bytes. Instead you could send a long value over a DataOutputStream which would use 8 bytes.
Note: you would need to correct for the latency between the client and the server otherwise the time will be always delayed.
A simple way to address this is for the client to send a message to the server with a timestamp as long, the server responds with it's own time stamp and you can assume that the delay is half the round trip time. You can then apply an EWMA (Exponentially Weighted Moving Average) to get a reason average of the difference in the clock on the server and the client.

Server/client communications not working java

I am trying to write a program in which the client requests the number of cores the server has. I do this as follows:
Client:
public void actionPerformed(ActionEvent e) {
try {
Socket clientSocket = new Socket("128.59.65.200", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String numberOfCores = inFromServer.readLine();clientSocket.close();
System.out.println(numberOfCores);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
Server:
public static void sendNumberOfCores() {
Thread coresThread = new Thread() {
public void run() {
try {
int numberOfCores;
ServerSocket welcomeSocket = new ServerSocket(6789);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
numberOfCores = Runtime.getRuntime().availableProcessors();
outToClient.write(numberOfCores);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
coresThread.setName("Wait for core request thread");
coresThread.start();
}
However, when I load the server and hit the button on my gui which runs the client code, nothing happens and the button just gets stuck. What is causing this?
Thank you.
Server not initialized on the 6789 port and make sure you do that in a separate thread.
Some thing like this.
In Server class:
--Make an inner class say MyServer
class MyServer implements Runnable{
final int BACKLOG=10; //10 is the backlog,if your server wishes to serve requests.
final int PORT = 6789;
public void run(){
try {
ServerSocket serverSocket = new ServerSocket(PORT,BACKLOG); //10 is the backlog,if your server wishes to serve conncurrent requests.
while (true) {
Socket ClientConnetion = serverSocket.accept();
//Now whatever you want to do with ClientConnection socket you can call
}
} catch (Exception e) {
e.printStackTrace();
}
}
--Start this thread in you main server class
MyServer mys=new MyServer();
Thread r=new Thread(mys);
mys.start();
It ended up that I was sending an integer when the code on the client was waiting for a string.

ServerSocket java-server reads input only once?

I have written a java server and here is the code:
try
{
ss = new ServerSocket(8080);
while (true)
{
socket = ss.accept();
System.out.println("Acess given");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//out = new PrintWriter(socket.getOutputStream(),true);
line = in.readLine();
System.out.println("you input is :" + in.readLine());
}
}
And an iphone application is the client and there is the code for it:
- (void)viewDidLoad {
[super viewDidLoad];
socket = [[LXSocket alloc]init];
if ([socket connect:#"10.211.55.2" port:8080]) {
NSLog(#"socket has been created");
}
else {
NSLog(#"socket couldn't be created created");
}
#try {
}#catch (NSException * e) {
NSLog(#"Unable to send data");
}
[super viewDidLoad];
}
-(IBAction)sendData{
[socket sendString:#"A\n"];
}
I am having 2 problems here: first is that the server is only reading the input once. The second is that when ever I try to output the data it doesn't output until I have called the method twice (clicked on the uibutton twice). Not sure what is happening here. What am I doing wrong?
You are creating a new reader everytime in your while loop. Instead move the code outside the while loop and block on the readLine() call.
socket = ss.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream());
String line = "";
while ( true) {
line = in.readLine();
System.out.println("you input is :" + line);
if ( "Bye".equals(line) )
break;
}
Here is an example server side program.
Since alphazero posted the pattern, I will post a brief stripped down implementation:
This is the Server:
try {
ServerSocket ss = new ServerSocket(portNumber);
logger.info("Server successfully started on port " + portNumber);
// infinite loop that waits for connections
while (true) {
SocketThread rst = new SocketThread(ss.accept());
rst.start();
}
} catch (IOException e) {
logger.info("Error: unable to bind to port " + portNumber);
System.exit(-1);
}
The SocketThread is something like:
public class SocketThread extends Thread {
private Socket communicationSocket = null;
public SocketThread(Socket clientSocket) {
communicationSocket = clientSocket;
try {
input = new ObjectInputStream(communicationSocket.getInputStream());
} catch (IOException e) {
logger.info("Error getting communication streams to transfer data.");
try {
communicationSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void run() {
boolean listening=true;
DataObject command = null;
while (listening) {
try {
Object currentObject = input.readObject();
if (currentObject != null
&& currentObject instanceof DataObject) {
command = (DataObject) currentObject;
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// If we got to this point is because we received a request from
// the client
// we can exit the loop
listening = false;
}
}
}
}
Note: "DataObject" is just a custom class which could be more practical since you can read the Dataobject itself from the socket without worrying about how many bytes you are reading, etc. Only condition is that DataObject is flagged as Serializable.
Hope it helps.
Tushar,
The general pattern is this (almost java but pseudo-code):
while (server-socket is accepting new connections)
{
// The server-socket's job is to listen for connection requests
// It does this typically in a loop (until you issue server-shutdown)
// on accept the server-socket returns a Socket to the newly connected client
//
socket s = server-socket.accept-connection();
// various options here:
//
// typically fire off a dedicated thread to servie this client
// but also review NIO or (home-grown) connection-map/handler patterns
// the general pattern:
// create a dedicated thread per connection accepted.
// pass Socket (s) to the handler method (a Runnable) and start it off
// and that is it.
// Here we use the general pattern and create a dedicated
// handler thread and pass of the new connections' socket reference
//
Thread handler-thread = new Thread (handler-routine-as-runnable, s);
handler-thread.start();
}

Categories