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).
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);
}
I created an simple server/client application,but I could not use this one with two parameters,so I want to add two numbers on server,Two numbers sent to server as parameter.
But When I sent two parameters to server,the client and server begun to wait for anything and nothing happened,as if running both of them without results.
Server
class Server3 public static void main(String[] args)
{
try
(
ServerSocket server=new ServerSocket(12345);
Socket client=server.accept();
PrintWriter output=new PrintWriter(client.getOutputStream(),true);
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
)
{
int result=0;
String input;
while((input=in.readLine())!=null)
{
System.out.println(input);
result+=Integer.parseInt(input)*3;
//output.println("The result to client is "+result);
//output.flush();
}
output.println("The result to client is "+result);
output.flush();
}
}
}
Client
import java.net.*;
import java.io.*;
import java.util.*;
class Client3
{
public static void main(String[] args) throws Exception
try
(
Socket toServer=new Socket("localhost",12345);
PrintWriter output=new PrintWriter(toServer.getOutputStream(),true);
BufferedReader in=new BufferedReader(new InputStreamReader(toServer.getInputStream()));
)
{
String temp,input;
for(int i=0;i<args.length;++i)
{
output.println(args[i]);
output.flush();
}
while((input=in.readLine())!=null);
{
input=in.readLine();
}
System.out.println(input);
}
}
}
Do you hane any idea?
I tried a lot of things?
But never Can I use more numbers,I can use only without while condition.
You have to use a protocol to communicate between client and server. It's just like a way to talk about or you can say some rules to be followed while talking.
Sample code: (Read inline comments)
Here I used DONE as a token to tell the server that client has sent all the numbers and now I am waiting for the result.
Server:
Break the loop once all the numbers are received and sent the result back to client.
public class Server {
public static void main(String[] args) throws IOException {
try (ServerSocket server = new ServerSocket(12345);
Socket client = server.accept();
// flush automatically
PrintWriter output = new PrintWriter(client.getOutputStream(),true);
BufferedReader in = new BufferedReader(new InputStreamReader(
client.getInputStream()));) {
int result = 0;
String input;
while ((input = in.readLine()) != null) {
System.out.println(input);
if (input.equals("DONE")) { // Server received token DONE
break; // break the loop
}
result += Integer.parseInt(input) * 3;
}
// sent the result back to client
output.println("The result to client is " + result);
// output.flush();
// no need to call flush here
// because you have already set it to flush automatically
}
}
}
Client:
You don't need to put a while((input=in.readLine())!=null); to wait for received result.
public class Client {
public static void main(String[] a) throws Exception {
try (Socket toServer = new Socket("localhost", 12345);
// flush automatically
PrintWriter output = new PrintWriter(toServer.getOutputStream(),true);
BufferedReader in = new BufferedReader(new InputStreamReader(
toServer.getInputStream()));) {
for (int i = 0; i < args.length; ++i) {
output.println(args[i]); // sent all the numbers
// output.flush();
// no need to call flush here
// because you have already set it to flush automatically
}
output.println("DONE"); // Client sent token DONE
String input = in.readLine(); // read the result
System.out.println(input);
}
}
}
output: (server)
1
2
DONE
output: (client)
The result to client is 9
I really don't know what the problem is. I am learning Java and I am following Oracle's Docs on networking. I simply did a copy and paste for their example and get this error. Could someone be kind enough to help? Thank you :)
Here's the code from Oracle:
import java.net.Socket;
import java.net.ServerSocket;
public class EchoServer {
public static void main(String[] args) throws Exception {
// create socket
int port = 4444;
ServerSocket serverSocket = new ServerSocket(port);
System.err.println("Started server on port " + port);
// repeatedly wait for connections, and process
while (true) {
// a "blocking" call which waits until a connection is requested
Socket clientSocket = serverSocket.accept();
System.err.println("Accepted connection from client");
// open up IO streams
In in = new In (clientSocket);
Out out = new Out(clientSocket);
// waits for data and reads it in until connection dies
// readLine() blocks until the server receives a new line from client
String s;
while ((s = in.readLine()) != null) {
out.println(s);
}
// close IO streams, then socket
System.err.println("Closing connection with client");
out.close();
in.close();
clientSocket.close();
}
}
}
It seems you copied it wrong.
I was able to run it on the first try.
echo:
hi mom
echo: hi mom
how are you?
echo: how are you?
I took what they had and remixed it a bit to make it simpler (less code, and it does the same thing). You need JDK 7, but you can drop these in an IDE. Hit run on Server first. Then hit run on client. Then click the output area of the IDE and start typing in the client. Or you can run them from the command line.
package com.examples;
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String... args) throws IOException {
int port;
if ( args.length != 1 ) {
System.out.println("listening to port 9999");
port = 9999;
} else {
port = Integer.parseInt ( args[ 0 ] );
}
try (
ServerSocket serverSocket =
new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
}
}
}
}
The above uses the new JDK 7 try with auto close syntax. You want this.
Then here is the remixed client.
package com.examples;
import java.io.*;
import java.net.*;
public class EchoClient {
public static void main ( String... args ) throws IOException {
String host;
int port;
if ( args.length != 2 ) {
System.out.println("binding to port localhost:9999");
host = "localhost";
port = 9999;
} else {
host = args[ 0 ];
port = Integer.parseInt ( args[ 1 ] );
}
try (
Socket echoSocket = new Socket ( host, port );
PrintWriter out =
new PrintWriter ( echoSocket.getOutputStream (), true );
BufferedReader in =
new BufferedReader (
new InputStreamReader ( echoSocket.getInputStream () ) );
BufferedReader stdIn =
new BufferedReader (
new InputStreamReader ( System.in ) )
) {
System.out.println("Type in some text please.");
String userInput;
while ( ( userInput = stdIn.readLine () ) != null ) {
out.println ( userInput );
System.out.println ( "echo: " + in.readLine () );
}
}
}
}
The server is as follows:
We grab the port number from the args passed to main or just set them to 9999 if they are not passed on command line.
int port;
if ( args.length != 1 ) {
System.out.println("listening to port 9999");
port = 9999;
} else {
port = Integer.parseInt ( args[ 0 ] );
}
Then in the try statement parens we open up our server socket streak gak
ServerSocket serverSocket =
new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
If the above does not make sense, then you have to learn more about streams. Go to the tutorial on input/output (read and writing files), then come back to this.
Basically it is wrapping the output stream of the server socket in PrintWriter and wrapping the input stream in a BufferedReader. The Java I/O API is a bit daunting if you have not worked with it before so I suggest starting with the I/O tutorial a bit.
Here is the original:
EchoClient
EchoServer
Based on where you got messed up, start reading about IO-Streams, then IO-Character Streams.
Then come back to this after a few hours of background.
In and Out are not defined types. Thus you get the error. Change it to another defined type and it should be fine.
Perhaps you were trying to do something like this?
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
From the EchoServer.java example, I assume that In and Out should be PrintWriter and BufferedReader, respectively (or some other output and input stream objects, as In and Out are meaningless unless you wrote the objects yourself):
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader
(clientSocket.getInputStream()));
If you haven't already, check out the Reading from and Writing to a Socket Tutorial.
What Oracle doc are you looking at? (link please)
Lesson: All About Sockets looks like what you should be reading. It has the following EchoServer:
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java EchoServer <port number>");
System.exit(1);
}
int portNumber = Integer.parseInt(args[0]);
try (
ServerSocket serverSocket =
new ServerSocket(Integer.parseInt(args[0]));
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
I improved the example a bit. EchoServer no longer terminates after first connection (it was annoying me). I tried to use System.console(), but it would not work in my IDE so I canned it.
Notice the use of Scanner (in the EchoClient) which cut down the code quite a bit and made the example much more readable.
Client:
try (
Socket echoSocket = new Socket ( host, port );
PrintWriter socketOut =
new PrintWriter ( echoSocket.getOutputStream (), true );
Scanner socketIn = new Scanner( echoSocket.getInputStream () );
Scanner console = new Scanner(System.in);
) {
System.out.println("Type in some text please.");
while ( console.hasNextLine () ) {
String userInput = console.nextLine ();
socketOut.println ( userInput );
System.out.println ( "echo: " + socketIn.nextLine () );
}
}
Here is a better example and I think it also answers the original question better.
Full server with while true loop:
package com.examples;
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String... args) throws IOException {
int port;
if ( args.length != 1 ) {
System.out.println("listening to port 9999");
port = 9999;
} else {
port = Integer.parseInt ( args[ 0 ] );
}
while(true) {
try (
ServerSocket serverSocket =
new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
}
}
}
}
}
Notice how the main method works even if the end user (a developer learning Sockets) is running in an IDE and passing args are not convenient. When I write examples, I spend a lot of time trying to simplify and amplify the topic I am covering with as little clutter as possible.
Here is the client once again, notice how the code is much shorter using Scanner than BufferredReader and it is more logical (you don't have to check for null, if there are lines process them).
Full Client
package com.examples;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class EchoClient {
public static void main ( String... args ) throws IOException {
String host;
int port;
if ( args.length != 2 ) {
System.out.println("binding to port localhost:9999");
host = "localhost";
port = 9999;
} else {
host = args[ 0 ];
port = Integer.parseInt ( args[ 1 ] );
}
try (
Socket echoSocket = new Socket ( host, port );
PrintWriter socketOut =
new PrintWriter ( echoSocket.getOutputStream (), true );
Scanner socketIn = new Scanner( echoSocket.getInputStream () );
Scanner console = new Scanner(System.in);
) {
System.out.println("Type in some text please.");
while ( console.hasNextLine () ) {
String userInput = console.nextLine ();
socketOut.println ( userInput );
System.out.println ( "echo: " + socketIn.nextLine () );
}
}
}
}
I also renamed the variables in Client so it is more clear what they are doing.
Now that I write this I realize I could do the same for the EchoServer.
I might add a set of socket utils to Boon.
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!