Im trying to solve an exercise on JAVA IO . The problem i get is that the messages are not coming on the correct order. For example this is what happens:
Run server
Run Client
Type Password
Two
Three
Wrong password
One
Wrong password
Trial
Waiting for sentence
T
TRIAL
Your IP address is :/
Your Socket is : 4351
Current date is : 2011/05/18 15:45:13.
So for some reason the messeges are not on right order.
This is the code:
import java.io.*;
import java.net.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class TCPServer {
public TCPServer() {
}
public static void main(String args[])
throws Exception {
String clientSentence;
String capitalisedSentence;
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
ServerSocket welcomeSocket = new ServerSocket(4351);
while (true) {
Socket clientSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
DataOutputStream outToClient =
new DataOutputStream(clientSocket.getOutputStream());
boolean correctPass = false;
while (!correctPass) {
if (getPassword(clientSocket,inFromClient,outToClient)) {
correctPass = true;
}
}
outToClient.writeBytes("Waiting for sentence"+"\n");
clientSentence = inFromClient.readLine();
capitalisedSentence = clientSentence.toUpperCase();
outToClient.writeBytes(capitalisedSentence + "\n"
+ "Your IP address is :" + clientSocket.getInetAddress() + "\n"
+ "Your Socket is : " + clientSocket.getLocalPort() + "\n"
+ "Current date is : " + dateFormat.format(date) + "\n");
}
}
private static boolean getPassword(Socket clientSocket,BufferedReader inFromClient,DataOutputStream outToClient) throws Exception {
boolean passed = false;
outToClient.writeBytes("Type password." + "\n");
while (!passed) {
String password = inFromClient.readLine();
if (password.equals("1")) {
passed = true;
} else {
outToClient.writeBytes("Wrong Password" + "\n");
}
}
return true;
}
}
import java.io.*;
import java.net.*;
class TCPClient {
public static void main(String args[])
throws Exception {
String sentence;
String modifiedSentence = "";
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 4351);
DataOutputStream outToServer =
new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer =
new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
do{
while(inFromServer.ready()){
System.out.println(inFromServer.readLine());
}
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + "\n");
}while(true);
// close the socket and the connection
}
}
Note that the messages aren't so much in the wrong order, as that you are one behind on the replies from the server. I think your problem is just that you send a message, and then immediately go back to the top of the loop and check if there is an incoming message. If it is not there immediately, you ask for another input. But what if the server does not reply in between the time when you send the message and go back to the top of the loop? This will happen in a nanosecond.
So you're asking a question, and then if you don't get an immediate reply, you're promptly asking another question. Then you display the reply to the first question and ask the third question. Etc. You need to be a little more patient. It's been a while since I've done socket programming, but I think you really need to wait for a reply, don't just say that if there is no reply, barrel ahead.
the problem is you are using a DataOutputStream for output and a Reader for input -- instead try using a PrintWriter (which offers a println!) for output and the Reader you currently use for reading. It's not a good idea to mix a Stream and a Reader/Writer!
Related
I have a Server and Client in my little demo program, where I send some string data from the Client to the Server, and after that resending this data for the Client, which also writes it out to the console. I was confused by PrtintWriter's flush method, which is - according to the JAVA documentation, - flushes the stream. After some researching I'm getting familiar with the concept of autoflash: when the autoFlash parameter is true println, printf, or format methods will flush the output buffer. The only thing what I don't understand here is why should I use the PrintWriter's flush method in the loop and not after the loop. (In my case I use PrintWriter in the Server side.) Autoflash does the same because the println() method is in the loop too. When I use flush after the loop my string data does not appear on the console. Thank you for your guidance and help in advance!
The Client:
public class ClientDemo {
public static void main(String[] args) throws IOException {
final String CLIENTNAME = "<CLIENT>:";
final String SERVERADDRESS = "localhost";
final int PORT = 12312;
try {
Socket socket = new Socket(SERVERADDRESS, PORT);
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
Scanner scanner = new Scanner(socket.getInputStream());
System.out.println(CLIENTNAME + "Client starts");
List<String> lista = getList();
for(String userInput : lista){
out.println(userInput);
System.out.println("echo: " + scanner.nextLine());
}
} catch(IOException e) {
System.out.println(CLIENTNAME + "Error connecting to the server:" + e.getMessage());
}
}
private static List<String> getList(){
List<String> result = new ArrayList<>();
result.add("egy");
result.add("ketto");
result.add("harom");
result.add("negy");
result.add("ot");
result.add("hat");
result.add("het");
result.add("nyolc");
result.add("kilenc");
result.add("tiz");
return result;
}
}
The Server:
public class ServerDemo {
public static void main(String args[]) throws IOException {
final int PORT = 12312;
final String SERVERNAME ="<SERVER>:";
try {
ServerSocket serverSocket = new ServerSocket(PORT);
Socket socket = serverSocket.accept();
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
Scanner scanner = new Scanner(socket.getInputStream());
System.out.println(SERVERNAME + "Server starts...");
String inputLine;
while(scanner.hasNext()) {
inputLine = scanner.nextLine();
printWriter.println(inputLine);
printWriter.flush();
}
} catch (IOException e) {
System.out.println(SERVERNAME + "Error handleing client...");
}
}
}
You don't have to call flush after writing every line. You are blocking the I/O by doing that. By calling flush you are ensuring that every line you are writing to the socket is actually written and not just buffered (to be written later). Buffering improves the I/O performance. But here it seems that for some reasons, you are not leveraging the advantages the buffering gives. You are blocking until the write is completely done.
I have written a simple client server program. I am able to send text from client to server and vice-versa. But after printing the Server's data on the client, I am not able to print anything on the Client's CLI.
I am not sure what I am doing wrong. I suspect bug in the lines commented "Bug Here". I am unable to find what is wrong in those lines.
Please find my code below.
ATMClient.java
import java.io.*;
import java.net.*;
public class ATMClient
{
public static void main(String args[])
{
try
{
Socket sock = new Socket("localhost", 9010);
sock.setSoTimeout(10000);
System.out.println("Connection established");
String data = null;
InputStreamReader input = new InputStreamReader(sock.getInputStream());
BufferedReader bread = new BufferedReader(input);
BufferedReader brCli = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter text to be sent to Server: ");
String strCli = brCli.readLine();
PrintWriter pwrite = new PrintWriter(sock.getOutputStream(), true);
pwrite.println(strCli);
// Bug Here: The control in not coming out of the while loop
while((data = bread.readLine()) != null)
{
System.out.println(data);
}
// Bug Here: The following line does not get printed.
System.out.print("Enter an Option: ");
pwrite.close();
bread.close();
input.close();
}
catch(IOException ex)
{
System.err.println(ex);
}
}
}
ATMServer.java
import java.io.*;
import java.net.*;
public class ATMServer
{
public static void main(String args[])
{
try
{
ServerSocket server = new ServerSocket(9010);
Socket client = server.accept();
System.out.println("Connection Established");
InputStream input = client.getInputStream();
BufferedReader bufread = new BufferedReader(new InputStreamReader(input));
PrintWriter pwrite = new PrintWriter(client.getOutputStream(), true);
pwrite.println("1. Deposit");
pwrite.println("2. Withdrawal");
pwrite.println("3. Balance");
pwrite.println("4. Exit");
String data = null;
while((data = bufread.readLine()) != null)
{
System.out.println(data);
}
pwrite.close();
bufread.close();
input.close();
server.close();
client.close();
}
catch(Exception ex)
{
System.err.println(ex);
}
}
}
Output:
user1$ java ATMServer
Connection Established
hello
user1$ java ATMClient
Connection established
Enter text to be sent to Server: hello
1. Deposit
2. Withdrawal
3. Balance
4. Exit
Deposit
^C user1$
Can you help me in figuring out how to get an input on Client's console ? Thanks.
As long as the input stream from the remote socket is open,
bread.readLine() will never return null,
and therefore this loop will never end:
while((data = bread.readLine()) != null)
{
System.out.println(data);
}
You need to add some kind of signal, for example the text "ENDMSG". The server should send this when it's done talking to the client, and the client should recognize it as such, and exit from the loop. For example:
while((data = bread.readLine()) != null)
{
if (data.equals("ENDMSG")) {
break;
}
System.out.println(data);
}
The following is a simple socket-level program. Once a connection is established, the server speaks for as long as he/she wants provided that the message does not end in a period - then the client can speak for as long as he/she wants provided that the conversation does not end in a period - the conversation alternates like this until someone shuts the program down --
I can't get the until there is a period part down ...
Else, I would not have a problem - there would be a one-one interaction
Once one person writes, it stays their turn forever ...
import java.io.*;
import java.net.*;
public class ChatterServer {
final static int SERVER_PORT = 3333;
public static void main(String [] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
System.err.println("Waiting for a client");
Socket clientSocket = serverSocket.accept();
System.out.println("Connection requested from: " + clientSocket.getLocalAddress());
PrintStream toClient = new PrintStream(clientSocket.getOutputStream(), true);
BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
toClient.println("Whatcha want?");
String incoming = fromClient.readLine();
while(incoming != null) {
System.out.println(incoming);
System.out.print("Your turn>");
String myReply="";
//this part does not work
while ( myReply.substring( myReply.length() ) .equals(".") == false){
myReply = keyboard.readLine();
toClient.println(myReply);
}
incoming = fromClient.readLine();
}
}
}
import java.io.*;
import java.net.*;
public class ChatterClient {
final static int SERVER_PORT = 3333;
public static void main(String [] args) throws Exception {
Socket serverSocket = new Socket(args[0], SERVER_PORT);
PrintStream toServer =
new PrintStream(serverSocket.getOutputStream(), true);
BufferedReader fromServer = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
String incoming = fromServer.readLine();
while(incoming != null) {
System.out.println(incoming);
System.out.print("Your turn>");
String myReply="";
while ( myReply.substring( myReply.length() ) .equals(".") == false){
myReply = keyboard.readLine();
toServer.println(myReply);
}//end while
incoming = fromServer.readLine();
}//end while
}//end main
}//end ChatterClient class
Better would be to use the endsWith method. It will work just fine, and is cleaner to look at.
while (!myReply.endsWith(".")){...}
While I agree with using String.endsWith the actual problem in the code is that someString.substring(someString.length()) will always be an empty string. You wanted someString.substring(someString.length()-1).
I have implemented a simple chat program in Java . However when I run the code and try to send messages from client I get this as output on Server side
For example:
Client : hi
Server: ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=2000]
I get such a response from the client for any message I send..I am basically working on localhost
Can anyone help solve my problem?
My java code :
class Client
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter the key value");
int key=Integer.parseInt(br.readLine());
int random=(int)(Math.random()*50);
System.out.println(random);
int response=((int)random)%(key);
System.out.println(key);
System.out.println("response generated is "+response);
System.out.println("Authentication begins");
Socket echoSocket = new Socket("127.0.0.1", 2500);
BufferedReader sin=new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
PrintStream sout=new PrintStream(echoSocket.getOutputStream());
BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = null;
String s;
DataOutputStream clientout=new DataOutputStream(echoSocket.getOutputStream());
clientout.writeInt(random);
clientout.writeInt(key);
clientout.writeInt(response);
System.out.println("client is"+response);
System.out.println("chat is started");
while (true)
{
System.out.print("Client : ");
s=stdin.readLine();
sout.println(s);
s=sin.readLine();
System.out.print("Server : "+s+"\n");
if ( s.equalsIgnoreCase("BYE") )
break;
}
echoSocket.close();
sin.close();
sout.close();
stdin.close();
}
}
class Server
{
public static void main(String args[]) throws IOException
{
int random3=(int)(Math.random()*50);
int response2;
int response3;
int random2;
int key2;
ServerSocket s= new ServerSocket(2500);
Socket echoSocket=s.accept();
DataInputStream clientin=new DataInputStream(echoSocket.getInputStream());
BufferedReader cin=new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
PrintStream cout=new PrintStream(echoSocket.getOutputStream());
BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));
String s1;
random2=clientin.readInt();
key2=clientin.readInt();
response2=clientin.readInt();
System.out.println(key2);
response3=(random2)%(key2);
System.out.println("server is"+response2);
if(response2==response3)
{
System.out.println("client is authenticated..chat starts");
while (true)
{
s1=cin.readLine();
if (s1.equalsIgnoreCase("END"))
{
cout.println("BYE");
break;
}
System. out.print("Client : "+s+"\n");
System.out.print("Server : ");
s1=stdin.readLine();
cout.println(s1);
}
}
s.close();
echoSocket.close();
cin.close();
cout.close();
stdin.close();
}
}
You get the output because you are using the wrong variables. The variable you should print from the server is s1 and not s.
Variable s refers to the socket, that's why you are getting the socket info instead of the client's response
s1=cin.readLine();
if (s1.equalsIgnoreCase("END"))
{
cout.println("BYE");
break;
}
System. out.print("Client : "+s1+"\n"); // note that this should be s1 and not s
As a good practice, you should name your variable clearly so you and others can always read the code. Having s, s1 and so on will just get you confused later as the code gets larger. It's also a good habit to have and make other engineers who are working with you happier :)
Without showing any code, it's next to impossible to tell. Please post some.
However, the address 0.0.0.0 looks suspicious. If you're working off of localhost, try 127.0.0.1.
I have one problem, I learn how work with socket and I write programm with next code :
import java.net.*;
import java.io.*;
import java.util.*;
public class Client extends Thread{
public static void main(String args[])
{
try
{
Socket s = new Socket(args[0],Integer.parseInt(args[1]));
BufferedReader br=new BufferedReader(new InputStreamReader(System.in,"CP866"));
String str;
str=br.readLine();
str = str+"\n"+s.getInetAddress().getHostAddress()
+":"+s.getLocalPort();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
pw.println(str);
pw.flush();
while(true){
str=null;
if((str=br.readLine())==null)
break;
str = str+"\n"+s.getInetAddress().getHostAddress()
+":"+s.getLocalPort();
System.out.println(str);
pw.print(str);
pw.flush();
}
}
catch(Exception e)
{System.out.println("init error: "+e);}
}
}
Programm of server-side just print obtained message, first message normal print, but next message print in format :, when I cut 25-26 line - message not sent or not obtained.
Why?
You wrote print(str);. So you don't print a newline(\n). Your server-side uses also a BufferedReader (I supose). And he is reading until a newline.
So change to println(str);