probably a noobish Q:
So i made a very simple single-threaded server/client model. Now when i execute the program in the eclipse IDE it shows me System.out's of the server and not the ones from the client.
When i press terminate, the System.out.println lines that were supposed to be generated by Client show up.
I'm struggling with this for days now.. Hopefully someone can help me out.
Thanks in advance!
SERVER:
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args)
{
new Server();
}
public Server()
{
try
{
ServerSocket serverSocket = new ServerSocket(8000); //nieuw instantie van een ServerSocket
System.out.println("Waiting for clients..");
Socket socket = serverSocket.accept(); // lister for socket requests
while(true)
{
BufferedReader inputClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
DataOutputStream clientOutput = new DataOutputStream(socket.getOutputStream());
String clientInput = inputClient.readLine();
System.out.println("Server: clientInput= : " + clientInput);
InetAddress hostAddress = InetAddress.getByName(clientInput);
String iPaddress = hostAddress.getHostAddress();
System.out.println("Server: IP = : " + iPaddress);
clientOutput.writeBytes(iPaddress);
clientOutput.flush();
}
}
catch(IOException ex)
{
System.err.println(ex);
}
}
}
CLIENT:
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) {
new Client();
}
public Client()
{
try
{
Socket socket = new Socket("localhost", 8000);
DataOutputStream toServer = new DataOutputStream(socket.getOutputStream());
BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
toServer.writeBytes("google.com" + '\n');
String ip = fromServer.readLine();
System.out.println("Client: "+ ip);
}
catch(IOException ex)
{
System.err.println(ex);
}
}
}
When you start a client and a server program, they will have 2 separate consoles. Only one is visible at a time in the "Console" view of Eclipse. That is why you only see the server's.
You can switch between the active consoles with the "Display Selected Console" icon (it's a monitor icon) and also see the active console list.
Also you have a full-duplex connection. Both the client and the server can read/write. You use a DataOutputStream - BufferedReader representation for a one-way communication which is WRONG.
DataOutputStream writes binary data, BufferedReader reads text (character) data.
You should use one of the following pairings:
DataOutputStream - DataInputStream and use writeUTF() and readUTF() methods
OR
PrintWriter - BufferedReader and use println() and readLine() methods
clientOutput.writeBytes(iPaddress);
clientOutput.write("\n".getBytes());
clientOutput.flush();
Just add these lines (second line) in your Server class.
Reason
In your Client class you are reading a line from buffer reader but you have not send any character from server indicating end of line. So in the second line we are writing new line character indicating end of line.
When you close the server, connection get reset and available input are read. Thats why your Client prints if you close the server.
Optionally if you only want to modify your Client class you can write these lines
char [] a = new char[100];
int length = fromServer.read(a);
System.out.println("Client: "+(new String(a)).substring(0,length));
Instead of these
String ip = fromServer.readLine();
System.out.println("Client: "+ ip);
Ok so after indexing the line with an '\n' and putting the line :
Socket socket = serverSocket.accept();
inside the while loop in stead of inside try{} i got rid of all my problems.
Thanks, now i'll try to multithread this thing!
Related
I am currently working on a Java console application. It is run through the command prompt, connects to a server application coded in python and communicates with that server over TCP. My application sends "ISND" string to server which it accepts and in return server sends three images. The format in which Images are sent in is
Where "<"">" are not actually included. "ISND" is encoded into bytes using ascii. Size is the size of the image converted into bytes from int and it is always composed of 3 bytes regardless of the size of the image. For each individual image, a message in this format is sent.
I have been using BufferedReader to read server responses but at this point, I am at a loss on how to actually handle this message. I searched for ways to separate the incoming message into components since I know the length of the first two parts which are always fixed yet I couldn't find a way to actually accomplish that goal.
It has come to the point it feels like I am smashing my head into a wall. As such, I need advice from anyone that is more familiar with Java and Socket programming on how to handle this issue.
My current code
public class ImageLabeler {
/**
* #param args
*/
public static void main(String[] args) {
String IP = args[0];
System.out.println(IP + "\n");
String port = args[1];
System.out.println(port + "\n");
Socket clientSocket;
DataOutputStream outToServer = null;
BufferedReader inFromServer = null;
String serverResponse;
try {
clientSocket = new Socket(IP, Integer.parseInt(port));
outToServer = new DataOutputStream(clientSocket.getOutputStream());
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("Connection success\n");
} catch (IOException ex) {
System.out.println("Connection failed\n");
System.exit(0);
}
PrintWriter writer = new PrintWriter(outToServer, true);
try {
//outToServer.writeBytes("USER bilkentstu\\n");
//outToServer.flush();
//System.out.println("check\n");
writer.println("USER bilkentstu");
serverResponse = inFromServer.readLine();
System.out.println(serverResponse + "\n");
writer.println("PASS cs421f2019");
//outToServer.writeBytes("PASS cs421f2019\\r\\n");
//outToServer.flush();
serverResponse = inFromServer.readLine();
System.out.println(serverResponse + "\n");
writer.println("IGET");
//This is where I need to handle the incoming Image messages.
writer.println("EXIT");
} catch (IOException ex) {
Logger.getLogger(ImageLabeler.class.getName()).log(Level.SEVERE, null, ex);
}
System.exit(0);
}
}
Don't use buffered reader. You need to write the code reading a string from the InputStream of the socket one byte at a time.
My TCP Server is like this.
import java.net.*;
import java.io.*;
public class NetTCPServer {
public static void main(String[] args) throws Exception{
ServerSocket sock;
sock = new ServerSocket(1122);
if(sock == null)
System.out.println("Server binding failed.");
System.out.println("Server is Ready ..");
do{
System.out.println("Waiting for Next client.");
Socket clientSocket = sock.accept();
if(clientSocket!=null)
System.out.println("Clinet accepted. "+sock.getInetAddress().getHostAddress());
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
//DataInputStream in = new DataInputStream(clientSocket.getInputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String name;
String pass;
String line;
name = in.readLine();
pass = in.readLine();
for(int i=0;i<name.length();i++)
System.out.print(name.charAt(i)+","); //see more null char are receiving here
System.out.println("");
System.out.println(name +" "+ name.length()+" \n" + pass+" "+pass.length());
}while(true);
}
}
And respective TCP Client is as follows.
import java.net.*;
import java.io.*;
public class NetTCPClient {
public static void main(String[] args) throws Exception {
InetAddress addr = InetAddress.getByName("localhost");
Socket sock;
sock = new Socket(addr,1122);
if(sock == null)
System.out.println("Server Connection failed.");
System.out.println("Waiting for some data...");
DataInputStream input = new DataInputStream(sock.getInputStream());
DataOutputStream output = new DataOutputStream(sock.getOutputStream());
String uname="ram";
String pass="pass";
output.writeChars(uname+"\n");// \n is appended just make to readline of server get line
output.writeChars(pass+"\n");
}
}
When i compiled both and the server is started and there after client is run, i get following output.
Server is Ready ..
Waiting for Next client.
Clinet accepted. 0.0.0.0
,r,,a,,m,,
ram7 pass9
The null character after each character receive is somewhat strange to me. To make me unable to compare the string with something stored in server.
What is those null characters and where does they come from.
You write characters but read lines of bytes. That won't work. If you're going to write characters, you need to read characters with precisely the same encoding. If you're going to write bytes, you need to read bytes. Specify your protocol precisely at the byte level and follow the specification in both the client and the server.
See this question for more information.
Just trying to get a handle on sockets. The server and client are running in two different programs.
They seem to be connecting fine to each other but the client will not properly send its output to the server. The server just hangs. Here's the code:
Server:
private ServerSocket serverSocket;
private Socket client;
public void run() throws Exception {
serverSocket = new ServerSocket(20005);
while(currentState == Game.State.NORMAL) {
client = serverSocket.accept();
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String clientInput = in.readLine();
// Takes the client input string and does some simple game logic that returns a Gson object
Gson serverResponse = processInput(clientInput);
out.write(serverResponse.toString());
out.flush();
}
}
Client:
Socket clientSocket;
void run() throws Exception {
clientSocket = new Socket("192.168.0.24", 20005);
PrintWriter out;
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Print the state of the game - returns false if state is win or lose.
while(printState()) {
out = new PrintWriter(clientSocket.getOutputStream(), true);
// This method just takes some input from the console
String clientInput = getInput();
out.write(clientInput);
out.flush();
String serverResponse = in.readLine();
updateState(serverResponse);
}
}
}
There is some underlying game logic that is happening but it's pretty minor and should be irrelevant. I imagine I am just misunderstanding something fundamental here.
Thanks all.
Make sure you send a newline character to match the in.readLine() statement in the Server.
out.write(clientInput + "\n");
The same applys when sending data from Server->Client.
I would like to take text from a file and then send it to the server for it to capitalise before sending back to the client where it is printed out. How do I achieve this?
I can read one line and send that back to the client and I've managed to write multiple lines to the output stream (for the server to read) but I don't know what to do now..
I have a client that reads text from a file:
import java.io.*;
import java.net.*;
import java.util.Date;
public class Client
{
public static void main(String[] args)
{
try
{
// First create the input from keyboard
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Client Program");
// Next we need to find out the IP address and port number of the server
System.out.print("Enter IP Address of server: ");
String ip = input.readLine();
System.out.print("Enter port number of server: ");
String port_string = input.readLine();
// The port number needs to be an int, so convert the string to an int
int port = Integer.parseInt(port_string);
// Connect to the server
Socket sock = new Socket(ip, port);
// Create the incoming stream to read messages from
DataInputStream network = new DataInputStream(sock.getInputStream());
//Create the output stream to the client
DataOutputStream message = new DataOutputStream(sock.getOutputStream());
//Send message
//message.writeUTF("some text");
FileReader file = new FileReader("text.dat");
BufferedReader input_file = new BufferedReader(file);
// Loop until EOF
while (input_file.ready()){
// Read next line from the file
String line = input_file.readLine();
// Write line to server
message.writeUTF(line + "\n");
//System.out.println(line);
}
// Display our address
System.out.println("Address: " + sock.getInetAddress());
String line;
// Loop until the connection closes, reading from the network
while ((line = network.readUTF()) != null)
{
// Display the received message
System.out.println(line);
}
}
catch (IOException ioe)
{
// This is expected when the server closes the network connection
System.err.println("Error in I/O");
System.err.println(ioe.getMessage());
System.exit(-1);
}
}
}
And then a server that is supposed to take those strings and capitalise them:
import java.io.*;
import java.net.*;
import java.util.*;
public class Server
{
public static void main(String[] args)
{
try
{
// First create the input from the keyboard
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Server Program");
// Get the port to listen on
System.out.print("Enter port number to listen on: ");
String port_string = input.readLine();
// The port number needs to be an int, so convert the String to an int
int port = Integer.parseInt(port_string);
// Create a ServerSocket to listen on this address
ServerSocket server = new ServerSocket(port);
// Accept an incoming client connection on the server socket
Socket sock = server.accept();
// Create the output stream to the client
DataOutputStream network = new DataOutputStream(sock.getOutputStream());
//Create the incoming stream to read messages from
DataInputStream message = new DataInputStream(sock.getInputStream());
String newLine = inFromClient.readLine();
//Line to read
String line;
line = message.readUTF();
line = line.toUpperCase();
// Send message
network.writeUTF(newLine);
// Close sockets. This will cause the client to exit
sock.close();
server.close();
}
catch (IOException ioe)
{
System.err.println("Error in I/O");
System.err.println(ioe.getMessage());
System.exit(-1);
}
}
}
The problem is your server is reading the stream only once and closing the socket connection.
How will your server know you have finished sending the client data to the server socket ?
You should modify the server to listen to the port till you have finished sending the whole text. For that do something like -
String newLine;
while ( true )
newLine = inFromClient.readLine();
if (newLine.equalsIgnoreCase("END"))
{
break;
}
newLine = newLine.toUpperCase();
// Send message
network.writeUTF(newLine);
}
// Close sockets. This will cause the client to exit
sock.close();
server.close();
And from the client send "END" after all lines have been sent.
The easiest way is to use IOUtils from Apache Commons. IOUtils.readLines will return a list of Strings
Exact same question : Read/convert an InputStream to a String
I'm trying to learn sockets using Java and I sucessfully sent data to a ServerSocket running in my own machine. When I try to read from this socket using readline (so I can just echo my own sent message) my program hangs and won't return.
Here's the code:
public static void main(String[] args) throws UnknownHostException, IOException {
TCPClient cli = new TCPClient("127.0.0.1", "15000");
try {
cli.ostream.writeUTF("Teste");
String echo = cli.istream.readLine(); //it hangs in this line
System.out.println(echo);
}
TCPClient is a class I defined so I can test my program on a simpler interface before using swing on my homwework. here's the code:
public class TCPClient {
public DataOutputStream ostream = null;
public BufferedReader istream = null;
public TCPClient(String host, String port) throws UnknownHostException {
InetAddress ip = InetAddress.getByName(host);
try {
Socket socket = new Socket(host, Integer.parseInt(port));
ostream = new DataOutputStream(socket.getOutputStream());
istream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException ex) {
Logger.getLogger(TCPClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
My server is pretty simple. After the connection is estabilished, it enters in this loop and stays here until I close the client (because of the infinite loop). Afterwards, some exception handling returns it to the point before the connection started.
while(true){
String msg = istream.readLine();
System.out.println("Arrived on server: " + msg); //just works on debug
ostream.writeUTF("ACK: " + msg);
ostream.flush();
}
I don't see what am I missing.
PS: the wierd stuff is that if I debug the server, I can see the message arriving there (I can print it, for example), but this isn't possible if I just run this code. Does this have some concurrency relation I'm overlooking?
thx
The problem is that readLine tries reading a line. It will not return the line until it's sure that the end of line has been reached. This means that it expects either a newline character, or the end of the communication. Since the server doesn't send any newline char and doesn't close the stream, the client waits indefinitely.
cli.ostream.writeUTF("Teste");
Shouldn't this be containing a new line? Otherwise read method will be waiting for new line I think.
Also as suggested you can try flushing the ostream after writing to it.
writeUTF() doesn't write a line. See the Javadoc. writeUTF() is for use with readUTF(). And Readers are for use with Writers. So change the DataOutputStream to a BufferedWriter and call write() and then newline().