This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why isn't my application entering my if statement
I'm trying to write a console client-server application in Java; using sockets, I currently have a simple login system and a simple command system. The login system appears to work, and the connection seems to be working.
However, the command system does not seem to function at all, when the command is received by the server, it does not appear to send anything back.
So my main question is why doesn't my server send anything back to the client when the command is received?
Here is my Server:
import java.io.*;
import java.net.*;
class TCPServer2
{
public static void main(String argv[]) throws Exception
{
//error is caused by command being used differently to login & username/password strings.
//consider removing command as a set string and adding a statement which takes
//the readLine value, adds it to a string and the command is the value of said string.
//If string is = "listLanguages" do this else if = "getcost" do this else "invalid cmd".
ServerSocket welcomeSocket = new ServerSocket(6789);
Map<String, String> userDetails = new HashMap<String, String>();
userDetails.put("JOHN","UNCP");
userDetails.put("MATT","UNCP");
String Command;
String username;
String username1;
String password;
String password1;
String cmd;
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
username = inFromClient.readLine();
System.out.println("\nUsername received: " + username);
password = inFromClient.readLine();
System.out.println("\nPassword received: " + password);
username1=username.toUpperCase();
password1=password.toUpperCase();
if (userDetails.get(username1).equals(password1))
{
outToClient.writeBytes("Hello " + username1);
outToClient.writeBytes("\nOther users registered on the server currently include: \n");
for (String str : userDetails.keySet())
{
outToClient.writeBytes(str);
}
}
else
{
outToClient.writeBytes("Invalid Username and/or password.\n");
}
BufferedReader inFromClient2 =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient2 = new DataOutputStream(connectionSocket.getOutputStream());
Command = inFromClient2.readLine();
System.out.println("\nCommand received: " + Command);
if(Command.equals("listTranslations"))
{
outToClient2.writeBytes("English,Thai,Geordie,etc.");
}
else
{
if(Command.equals("getCost"))
{
outToClient2.writeBytes("£100\n");
}
else
{
outToClient2.writeBytes("Invalid Command");
}
}
}
}
}
Here is my client:
import java.io.*;
import java.net.*;
class TCPClient2
{
public static void main(String argv[]) throws Exception
{
String userName;
String passWord;
String loginInfo;
String loginInfo2;
String loginInfo3;
String command;
String commandInfo;
String commandInfo2;
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("Username: ");
userName = inFromUser.readLine();
outToServer.writeBytes(userName + "\n");
System.out.println("Password: ");
passWord = inFromUser.readLine();
outToServer.writeBytes(passWord + "\n");
loginInfo = inFromServer.readLine();
System.out.println(loginInfo);
loginInfo2 = inFromServer.readLine();
System.out.println(loginInfo2);
loginInfo3 = inFromServer.readLine();
System.out.println(loginInfo3);
System.out.println("Please enter a command: ");
command = inFromUser.readLine();
outToServer.writeBytes(command);
commandInfo = inFromServer.readLine();
System.out.println(commandInfo);
commandInfo2 = inFromServer.readLine();
System.out.println(commandInfo);
clientSocket.close();
}
}
Here's how it's supposed to work:
The client connects to the server,
The client asks user to login,
The user inputs his login info,
The server checks the login info,
The server tells the client it's logged in successfully,
The client asks the user to input a command,
The user inputs a command (to request a price),
The command is sent to the server,
The server sends back the desired in info,
It should then loop back to the user being asked to input a command.
However, it does not do this. It gets stuck after the user logs in, on the "Other users registered on the server currently include:" line, without printing any data.
Why is it doing this?
Why it's getting stuck is probably because both client and server are on a readLine() resulting in a deadlock. Client waits for incomming data and so is the server, Since this is a command promt client and server, and you have no "button" to send the data with.
I would add info showing which variable it is printing at the moment so you can easily follow where it gets stuck. Example:
loginInfo = inFromServer.readLine();
System.out.println("loginInfo client Side "+loginInfo);
This will show you that it's printing the loginInfo variable located in the client. Now you can easily follow the flows and locate where it's going wrong.
I've never done a command promt server/client (only gui), but when you are printing your list of users with your current design, you might want to to build a string with all usernames, send the whole string over to the client, and then the client separates the string with StringBuilder and prints the result. This is because the client will not know how many "usernames" the server will send
Have you tried flushing the buffer of the data output stream writer before you send the next line. I'm also curious why you use two different data output stream writers and input stream readers for one client. Couldn't you just use the same ones for both parts of your program.
The issue is with improper socket data read/write methods. You have to always flush() when you are writing data to sockets. If you comment line
//loginInfo3 = inFromServer.readLine();
//System.out.println(loginInfo3);
Then you can see that the client displays the "Please enter a command" but after you enter the command the socket is not flushed/closed so the server keeps waiting.
The main issue with the Server and Client code is proper hand shake. You have to write code in a block, open socket, write command, get response and close socket. This should be a common way of entering the data. You have clubbed sockets and writing data to the streams without proper flush/close, hence it is waiting at different points.
Related
I want to send objects from the server to the client in java sockets. I can send them from client to the server, however I am struggling to send them from server to client. I am new to Java so I'm still learning the basics. I know its something relatively minor that I need to do, however i am struggling with it at the moment. Can someone add the bits of code that i am missing?
Open another connection in another thread and let the client be server, and server be client. So in one thread you send A -> B, in another thread you open another socket and begin to send b B -> A.
The problem with low level sockets is that if one side is writing, the other should be listening. That means you have to implement command-query protocol, which is a heavy task. So with my proposal you will use two ports but you know that you will have 2 pipes of data flow.
A --8888--> B
A <--8889-- B
It will be easier if you are just starting with sockets.
You can use ObjectOutputStream to send an object through the socket and ObjectInputStream to receive one:
private ObjectOutputStream oos;
private ObjectInputStream ois;
public SocketHandler(Socket cs) {
this.oos = new ObjectOutputStream(cs.getOutputStream());
this.ois = new ObjectInputStream(cs.getInputStream());
}
public void sendObject(Object o) {
this.oos.writeObject(o);
this.oos.flush();
}
public Object receiveObject() {
return this.ois.readObject();
}
That was assuming you want to send and receive an Object. You can also use PrintWriter and BufferedReader to send and receive String messages and after parsing it:
private PrintWriter pw;
private BufferedReader br;
public SocketHandler(Socket cs) {
this.pw = new PrintWriter(cs.getOutputStream());
this.br = new BufferedReader(new InputStreamReader(cs.getInputStream()));
}
public void sendMsg(String msg) {
this.pw.println(msg);
this.pw.flush();
}
public String receiveMsg() {
return this.br.readLine();
}
Below I have an example of some Server-Side code that I used for an application a while ago, then I will give you an explanation as to what's going on here:
first you need to create your ServerSocket in order to accept client requests (as you already know):
ServerSocket serverSocket = new ServerSocket(1002);
while(true) {
Then you need to enter a while loop in order to receive requests for as long as the Server program is alive
Socket clientSocket = serverSocket.accept();
System.out.println("Connection made to: " + clientSocket);
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String messageString = "";
String line;
System.out.println("Enter while loop to retrieve client message...");
while((line = br.readLine()) != null) {
String clientRequestLine = line;
if(clientRequestLine.contains("check return user credentials")) {
String userNamePassWord = clientRequestLine.replace("check return user credentials", "");
userNamePassWord = userNamePassWord.trim();
String[] userNamePassWordSplitter = userNamePassWord.split(" ");
String userName = userNamePassWordSplitter[0];
String passWord = userNamePassWordSplitter[1];
System.out.println("Username: " + userName + "\nPassword: " + passWord);
boolean isValidUserNamePassWord = ReturnPatientCredentials.checkUserNamePassWord(userName, passWord);
if(isValidUserNamePassWord) {
System.out.println("valid");
out.println("valid");
}
else {
System.out.println("invalid");
out.println("invalid");
}
}
Above you need to start a BufferedReader in order to store an InputStream (the data) from the client socket. You also need to create a PrintWriter so that you can send data to the OutputStream and you need to pass your clientSocket as the argument for the OutputStream. Next you'll create variables to get the message and the "line" of date from the client and enter a while loop. You can then store the line in a variable and read the data or whatever you need to do. We use our PrintWriter (out) to send data back with the println() method and then we can break out of the loop when needed.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am currently learning about Sockets and my homework is to create a chat room where multiple clients can talk freely. The hint given by the teacher was that the chat room server only accepts the client when the client attempts to send a message. This homework is supposed to be done without using threads.
Following the hint given, I tried to create unbound ServerSocket and Socket in both the client and the server code. The key idea is that when the client attemps to send a message to the server, the client code would connect the unbound Socket, which will then trigger the server to connect the unbound ServerSocket and to accept the client.
However, when I run the code, both the server and client code are running, and they claim that all the connections are made, but I could not transmit messages between the client and the server at all.
I have tried finding answers online, but I could not find any. I would like to ask if my way of deciding when the server accepts the client is correct.
my ChatRoom Server:
public class ChatRoom {
public static void main(String[] args) throws Exception {
int portNum = 4321;
ServerSocket serverSocket = new ServerSocket();
int count = 1;
while (true) {
// redeclare everything each round
Socket socket = null;
PrintWriter out = null;
BufferedReader in = null;
BufferedReader stdIn = null;
String inputLine = null;
// accept each time round
serverSocket.bind(new InetSocketAddress(portNum));
socket = serverSocket.accept();
System.out.println("newly accepted!");
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
if (!((inputLine = in.readLine()).equals("Bye"))) {
System.out.println("Client says: " + inputLine);
out.println(stdIn.readLine());
out.flush();
System.out.println("Message Count: " + count);
count++;
}
else {
out.println(inputLine);
serverSocket.close();
socket.close();
out.close();
in.close();
}
}
}
}
my ChatRoomClient:
public class ChatRoomClient {
public static void main(String[] args) throws Exception {
String hostName = "localhost";
int portNumber = 4321;
Socket echoSocket = new Socket(); // creates an unbound socket
PrintWriter out = null;
BufferedReader in = null;
BufferedReader stdIn = null;
String userInput;
do {
out = null;
in = null;
stdIn = null;
// each time round the unbound socket attempts to connect to send a message
echoSocket.connect(new InetSocketAddress(hostName, portNumber));
System.out.println("successfully connected");
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
userInput = stdIn.readLine();
out.flush();
System.out.println("Server says: " + in.readLine());
}
while (!userInput.equals("Bye"));
// close everything
echoSocket.close();
in.close();
stdIn.close();
}
}
Thanks!
The hint given by the teacher was that the chat room server only accepts the client when the client attempts to send a message. This homework is supposed to be done without using threads.
The hint given by the teacher doesn't make sense. The client has to connect, then the server accepts. The client can't send a message without connecting first. Maybe the teacher really means that the client shouldn't connect until he has something to send?
Following the hint given, I tried to create unbound ServerSocket and Socket in both the client and the server code. The key idea is that when the client attemps to send a message to the server, the client code would connect the unbound Socket, which will then trigger the server to connect the unbound ServerSocket and to accept the client.
But that won't happen. It's impossible. If you try to connect to a port that isn't listening, you will get a ConnectException. The only way to put the port into listening state is to bind the ServerSocket. There is no magical back-door by which the server can possibly know that the client wants to connect so it should now do the bind.
This homework is supposed to be done without using threads.
Impossible to 'create a chat room where multiple clients can talk freely' that way, unless you are expected to use non-blocking I/O, or abuse the available() facility, or use a connection per message, but then I don't see how you can communicate one client's messages to the other clients, unless you're allowed to batch them up.
There are too many imponderable aspects of this assignment as you have described it. The question as posed doesn't actully make sense, and your proposed solution certainly doesn't. You should just go ahead and write your program the normal way, with a connect, an accept, and some I/O. Get it working while your teacher comes up with a clarification.
Ah... With out using thread for the server you will not be able to serve multiple clients. Anyway, your current codes have issues and your logic are not correct.
Your stdIn should be declare and instantiated outside of the loop, you don't need to keep on creating the stdIn object for each loop.
Your "in" socket accept() and echoSocket.connect() should also be outside of the loop, this is why you are not getting any answer from the server because you are not listening on the same line. It's like your phone, keep on FLASH to dial the new number each time. all point to the same server, but it is different connection.
So, the idea is to establish a connection between server and client (single connection) that can communicate both way (via input and output stream). Then you can loop and talk start with the client, then server receive, then server talk, then client receive then client talk.... until client say Bye...
for more: http://ta.cnci.org/basicirc
thought I would like to update, I managed to solve my problem without using threads. Just sockets haha. Thought it would be good to post my answer for reference..
my ChatRoom Server:
public class ChatRoomServer {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(4321);
while(true) {
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader
(new InputStreamReader(clientSocket.getInputStream()));
String inputLine = in.readLine();
System.out.println("Client says: " + inputLine);
in.close();
clientSocket.close();
}
}
}
my ChatRoom Client:
public class ChatRoomClient {
public static void main(String[] args) throws Exception {
String hostName = "localhost";
int portNum = 4321;
BufferedReader stdIn = new BufferedReader
(new InputStreamReader(System.in));
while (true) {
String userInput;
userInput = stdIn.readLine();
Socket echoSocket = new Socket(hostName, portNum);
PrintWriter out = new PrintWriter
(echoSocket.getOutputStream(), true);
out.println(userInput);
out.flush();
out.close();
echoSocket.close();
if (userInput.equals("Bye")) {
stdIn.close();
break;
}
}
}
}
I am practicing a simple java program where I am demonstrating simple client server interaction. The fist part of message from server gets transferred. Then program just continues to run and does not execute? Do we need to create a new socket for each individual traffic?
Server code
server = new ServerSocket(4587);
System.out.print("Starting the Server on port " + server.getLocalPort() + "\n");
System.out.println("Waiting for client...");
Socket client = server.accept();
BufferedWriter br = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
BufferedReader br1 = new BufferedReader(new InputStreamReader(client.getInputStream()));
br.write("Hello, you are connected to Server. What is your name?");
br.write("\n");
br.flush();
while((s=br1.readLine())!=null)
{
}
br.write("Thank you ");
br.newLine();
br.flush();
}
Client code
String stdin;
System.out.println("Attempting to connect to " + hostname + ":" + port);
client = new Socket("localhost", 4587);
System.out.println("Connection Established");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while ((stdin = br.readLine()) != null) {
System.out.println(stdin);
}
BufferedWriter br1 = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
br1.write("Mike");
br1.write("\n");
br1.flush();
while ((stdin = br.readLine()) != null) {
System.out.println(stdin);
}
Server Output
Starting the Server on port4587
Waiting for client....
Client Output
Attempting to connect to :123
Connection Established
Hello you are connected to Server, What is ur name
If this could help..after this both loop
Your server will first create a connection with the client through the accept method. If you wish to have multiple clients you will need to change your code accordingly to accept that.
On the client side, you're using \n to delineate the end of a message. This will work fine. Every time you send a new message use \n to indicate the end of the message.
On the server side, you should continue reading from I/O until you see the \n. At that point you have received the entire message. Process it and than start listening again.
Edit:
Since you are waiting for the name of the client, you could simply do the following on the server:
BufferedWriter bout = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
BufferedReader bin = new BufferedReader(new InputStreamWriter(client.getInputStream()));
// Wait for incoming name from client.
String name = bin.readline();
System.out.println(name);
// Send a reply.
bout.write("Thank you\n");
bout.flush();
Similarly, on the client (assuming bin and bout are defined the same as above):
// Send name to server.
bout.write("Name\n");
bout.flush();
// Get a response from the server and print to console.
String response = bin.readline();
System.out.println(response);
This is because BufferedReader has a default buffer = 8K when in reading process and this process is block I/O, so this will hang in that point. You should read the full message from client by server side.
Your problem is with the loop on the client side. It will be stuck in the loop as it waits to readlines sent from the server infinitely. (ie, after reading the first line from the server, it will expect more lines from the server and wait to read them).
To exit the loop you need to send an EOF signal or end of stream signal (according to the docs: http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#readLine%28%29)
I'm trying to create a simple library (hope to share it with the world) that will allow to send and receive commands to remote equipment via telnet.
I'm trying to keep the code as simple as possible and it's already working, but I can't seem to understand how the input stream is working;
I'm reading each line separately and normally input should stop at input "Username:" after which I should type in my username.
What actually happens is that after I detect that I've received this line and send a response it is already too late (new input has already been received).
Any idea how a telnet session actually works and how the last command (after which the remote equipment waits) is received?
import java.util.*;
import java.io.*;
import java.net.*;
public class telnet {
public static void main(String[] args){
try{
//socket and buffer allocation
Scanner scan = new Scanner (System.in);
Socket socket = null;
PrintWriter out;
BufferedReader in;
String input; // temp input
String input1="";
String buff = ""; // holds all the input
//socket and IO initialization
socket = new Socket("10.10.10.2", 23);
out = new PrintWriter(socket.getOutputStream(),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int i=0;
int j=0;
while(true){
input = in.readLine(); //printout given line
System.out.println("line "+i+":\n"+input);
if (input.contains("Username")){ //if reading 'username' send response
System.out.println("!got Username");
out.println("user");
continue;
}
if (input1.contentEquals(input)){ //if input is the same wait once then send ENTER
if (j==0){
System.out.println("!read same line. wait for new");
i++; j++;
continue;
}
else{
System.out.println("!no new line. sending ENTER");
out.println("\r");
i++;j=0;
}
} else {j=0;}
input1=""; //copy input to temp string to check if same line or new
input1.concat(input);
i++;
if (i==20) break;
}
//CLOSE
out.close();
in.close();
socket.close();
} catch(IOException e){}
}
}
A telnet server and telnet client don't just send plain text back and forth. There is a telnet protocol, and both the client and server can send commands to each other. The telnet server that you are connecting to may be trying to negotiate some setting change with your program, and your program may be interpreting the byte stream as lines of text.
The standard Unix telnet client program will suppress using the telnet protocol when it's not talking to an actual telnet server. Instead, it will fall back to sending text line-by-line and printing anything received from the server. This allows the program to be used to communicate with SMTP servers, HTTP servers, and the like. The telnet server doesn't necessarily have this fallback behavior; it may always assume that the client implements the protocol.
I have this client, the server information is not important. The output of this code is very random.
class Client {
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("127.0.0.1", 10004);//this will become the addr of the server you want to input.
InetAddress host = clientSocket.getInetAddress();
// System.out.println(host);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
boolean exit = false;
while (!exit) {
while (inFromServer.ready()) {
System.out.println(inFromServer.readLine());
}
String sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + "\n");
}
clientSocket.close();
}
}
If I run this in debug mode, it has always the correct result. E.g.
please insert password
the user types pass
pass correct
please type command
and you type command
etc
etc
When it's not in debug mode, all goes wrong. I don't even get the initial request from server. What is going on? I think the read line might be executed too fast?
in.ready() does not wait for any data to be available. It the server hasn't sent the data yet when you client reads that line, you're going to skip the readLine() completely.
Just remove that while and do a plain readLine().
If there are phases where you need to wait for multiple lines from the server, you'll need to implement more logic. Usually, the server will send an "end of message" marker to signify to the client that it is done. For example, when the server is done, it could send the message "END-OF-MESSAGE". In the client code, you would do:
boolean serverDone = false;
while (!serverDone) {
String message = in.readLine();
if (message == null) {
// handle this problem: the server has closed the connection
serverDone = true; // or return, or throw
} else if ("END-OF-MESSAGE".equals(message)) {
serverDone = true;
}
}