Hi guys, I have designed a simple text chat application but i am expereincing problems with it. I will explain.
Now I have 5 files. IntroFrame.java, Server.java, Server_thread.java, Client.java, and ListClients.java
Now to run the appliication, you need to compile and then run the IntroFrame.java file. This file opens a GUI that asks the user to select if the pc is the client or server. So the server option is selected. Once this is done, the server begins to run. The next step is to run the client. When the client is run, it must enter the server's hostname to connect, in this case it is 'localhost'. once this has been entered, it asks the user to select a nickname. PLEASE NOTE: for this part, the user has to enter 'Login: " followed by the desired nickname. If the nickname is not in use, then the server accepts the client. Once this is done the user can send messages by typing 'Post" followed by the message.
Now the problem I have is with regards to running 2 clients. When 2 clients are connected, if client A sends a message by typing 'Post...." the message should be sent to all connected clients. But in my application, the other clients do not receive the message. I have gone through my code a million times and I can't figure out why it doesnt work. I have pasted the Server.java, Server_thread.java, and Client.java file codes below. Could someone please take a look at it and let me know what the problem is? why does it not send the message to all connected clients? Any help would be appreciated. Thank you
public class Server
{
static Vector clients;
static Socket clientSocket;
public static void start_server()
{
//setting up the server socket to listen on a specified port
clients = new Vector(); //this creates a reference to a vector object. This will be used to store the list of clients connected to the server
ServerSocket ss = null; //this creates a reference to a ServerSocket object
boolean listening = true; //this creates a reference toa boolean object
clientSocket = null;
try
{
ss = new ServerSocket(9999); //this creates a new instance of the ServerSocket reference above. The object is then set to listen on port 9999
System.out.println("Server waiting for client connection...");
}
catch (IOException e) //the ServerSocket object throws an exception if it cannot listen on the specified port i.e. if the port is being used for another service
{
System.err.println("Unable to listen on port: 9999.");
System.exit(1);
}
//accepting a connection from a client
while (listening) //a while loop is used to put the ServerSocket in an indefinite listening state
try
{
//System.out.println("Server waiting for client connection...");
clientSocket = ss.accept();
System.out.println( "Connection established");
System.out.println("Server waiting for client login request...");
Server_thread sthread = new Server_thread(clientSocket);
clients.add(sthread); //the newly connected client is then added to the vector to maintain a current list of connected clients
sthread.start(); //in order to handle mutliple clients, a thread object is created and assigned to each client. This is how each client will communicate with server.
public class Server_thread extends Thread
{
Socket clientSocket; //creates a reference to a Socket object
Socket sock;
String nick_name; //creates a reference toa string object. This will be used to store the nick name tha the client selects
PrintWriter msg_out; //I/O //creates a reference to a printwriter object. This will handle the output
Scanner msg_in; //creates a reference to a scanner object. This will handle the input
public static Boolean connect_status; //creates a reference to a boolean object
Server_thread(Socket sock) //constructor method passes a Socket object parameter
{
super("Server_thread"); //calls the constructor method for the super class
connect_status= false; //sets the connect_status object to false therefore requiring the client to register
nick_name = "";
clientSocket = sock;
try
{
//sindesi I/O antikeimenwn me ta streams tou socket
msg_out = new PrintWriter(clientSocket.getOutputStream(), true);
msg_in = new Scanner (clientSocket.getInputStream());
}
catch (Exception e)
{
System.out.println(e);
}
}
//setting up communication betweek the server and the client
void begin()
{
//start the conversation with the client using the established protocols as specified in the Protocol class
//Protocol prot = new Protocol(); //a new instance of the protocol class is created. This specifies the format and sequence of the messages that will be sent between the client and server
//output = prot.processInput(null); //client communication from the server is initiated here. This is done by writing to the socket
//msg_out.println(output);
//while ((input = msg_in.nextLine()) != null) //performs communication with client by writing to the socket and reading from it
//while ((msg_in.nextLine()) != null)
try
{
//msg_in = new Scanner (clientSocket.getInputStream()); //gets the socket's input stream
//msg_out = new PrintWriter(clientSocket.getOutputStream(), true); //gets the socket's output stream
while (true)
{
String message = msg_in.nextLine(); //reads the input from the client
System.out.println(message);
//send(message);
if (message.startsWith("Login")) //if the client's message starts with login, the register method is called
{
register(message);
}
//method that is used to register a new client requesting to join the network
boolean register(String msg)
{
if (connect_status) //if the client is already registered, the message below is displayed
{
msg_out.println("You are already connected!");
return true;
}
boolean exists = false;
//System.out.println("Login" + msg.substring(5, msg.length())); //the substring method is called to reduce the message sent to omit the 'Login' part and simply display the user's desired nick name
//the server checks through the clients list vector using a loop.
//for each index in the vector, the connected client nick name is obtained by calling the get() method
//a temporary thread is then created and the connected client object is assigned to it
//the nick name of the temporary thread is then checked against the requested nick name.
//if they are the same, then it means the new client's desired nick name is already in use
//a break occurs and the server displays a new message requesting the user to select a different nick name
for (int i = 0;i < Server.clients.size();i++)
{
if (Server.clients.get(i) != null)
{
//System.out.println(msg.substring(7, msg.length()));
//System.out.println(msg);
Server_thread temp_thread = (Server_thread)Server.clients.get(i);
if ((temp_thread.nick_name).equals(msg.substring(7, msg.length())))
{
exists = true;
break;
}
}
}
if (exists)
{
msg_out.println("Choose a different nick name");
}
//however, if the temprorary thread object's nick name variable does not match the desired nick name
//the connection status is set to 'true' and the client's nick name is registered with the server
//the server then creates an instance of the ListClients class and calls the List() method on it
//in order to produce an updated list of currently connected clients and output the list to the client
else
{
connect_status = true;
nick_name = msg.substring(7,msg.length());
ListClients lc = new ListClients();
lc.List();
//System.out.println(lc.client_list);
System.out.println("New client " + nick_name + " has been successfuly registered to server");
//ListenerThread listener = new ListenerThread(clientSocket, nick_name);
//Thread lst = new Thread(nick_name);
//lst.listen();
//lst.start();
//listen();
// for (int i = 0;i < Server.clients.size();i++)
//{
//if (Server.clients.get(i) != null)
// {
int i = Server.clients.indexOf(this);
Server_thread temp_thread = (Server_thread)Server.clients.get(i);
System.out.println("Wating for messages...");
temp_thread.listen();
// Wait for a response from the server and display it.
Scanner input = new Scanner(System.in);
String userInput;
while ((userInput = input.nextLine()) != null)
{
//System.exit(1);
msg_out.println(userInput);
System.out.println(msg_in.nextLine());
// Use a BufferedReader to read data from the server.
//input = new Scanner (sock.getInputStream());
//String fromServer = msg_in.nextLine();
//System.out.println("FromServer: " + fromServer);
//String fromServer = msg_in.nextLine();
//System.out.println("FromServer: " + fromServer);
}
use [code] tags
if code is big to fit in a pair of screens better attach it as a file
Wanna install linux on a vacuum cleaner. Could anyone tell me which distro sucks better?
I had a nightmare last night. I was dreaming that I’m 64-bit and my blanket is 32-bit and I couldn’t cover myself with it, so I’ve spent the whole night freezing. And in the morning I find that my blanket just had fallen off the bed. =S(from: bash.org.ru)
//always looking for job opportunities in AU/NZ/US/CA/Europe :P
willCodeForFood(Arrays.asList("Java","PHP","C++","bash","Assembler","XML","XHTML","CSS","JS","PL/SQL")); USE [code] TAGS!Read this FAQ if you are new here. If this post was helpful, please rate it!
Unfortunately, it's not easy to find any more, even if you know it exists...
The greatest obstacle to discovery is not ignorance, but the illusion of knowledge...
D. Boorstin
Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.
Thanks for your prompt responses guys. I really appreciate it. Now I managed to solve the first problem but now I have a different problem. THe problem I have now is this:
When a client connects to the server, the server sends a login request via the printwriter. On the clients screen, this is displayed as 'Login:'. The client must then enter 'Login: ' followed by the desired nick name. Once the client does this, the server will check if there is already a user with that nick name. If not, then the user is added to the vector clients and a new thread is started. Now after the user is successfully logged in, the listen)message(0 method is called to listen for new messages. To send a message, the Client must then type 'Post ' followed by the message. This message is then sent to all users that are currently connected.
The problem I am facing is that when the client tries to send a message, when it is the only client connected, the message is send succesfully but then it cannot send any more messages until it receives a message from the server or another client. It is as if the client must receive a message before it can send. Now when, you have two clients connected, and client A sends a message, client B receives the message and then client A is unable to send any more messages until client b sends a message of its own.
I want the client to be able to send a message without having received one. For example if only one client is connected, I want that client to be able to send messages as many times as it wants even if it is not receiving any messages.
With regards to two connected clients, I want client A to be able to send a message to client B without having to receive a message from client B. I want simultaneous sending and receivng. Is this possible? So far i think the problem is with the BufferedReader and the Printwriter but I can't figure out exactly what it is. I have attached the files to this thread. i would really appreciate it if someone could help me with this before the weekend runs out. Thanks in advance guys
When posting code please don't post code which is full of commented out lines as it makes it difficult to read. Also adding some comments explaining what sections of code are supposed to do would help.
Your problem is in the client which writes the users input text and then reads from the socket stream twice before allowing the user to enter more text.
If the client does not receive 2 messages from the server it will block. There are fews ways around this such as having separate threads for writing and reading.
Thank you very much keang. Sorry about the commented out lines and sorry that it was difficult for you to read the code. I suspected that the problem was with the client. Now I changed it so that it reads from the socket stream only once. but it still does not work properly. In this case, the client has to wait for a message to be received before it can send one. What I want is for the client to be able to send messages at anytime i.e. the client does not have to receive a message before it can send one. Also, the client should be able to receive messages without having to send one. Can you tell me how to do this? If you could just give me an example of how to do this I would really appreciate it, like maybe a few lines of code that I can add to get it working. I am really interested in doing it by using separate threads for reading and writing but I am cautious. Now if I do decide to use separate threads for reading and writing, does that mean each client will be attached to 2 threads?
The best way to do this is using 2 threads but if that is beyond your skill and you just want to get something working you could try using the BufferredReaders ready() method to check if there is anything to read before actually calling read(). This will prevent your code blocking whilst waiting for a message.
You will have to repeatedly poll both your keyboard input stream and the socket input stream to give reasonable responsiveness and you will have to put some sleep(..) or wait(..) calls or you'll end up using 100% of the processor resource and typing will become really unresponsive.
Note: I've never tried this and don't know how robust a solution this will be.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.