Java loop to check for inputstream reader - java

I have a server and client.java which can send and accept a message both ways via input and output stream but as soon as there is a connection a message is sent and then the server closes its self, so far I have put the buffered reader ect. in a finally block which is only activated when e == true (e for exit so I can stop it when I want) but it still stops the build after sending/receiving a message
1st question how can I stop it from closing its self?
2nd question how can I put input stream reader in a loop to continually test for input from client.java?
Client.java
package client;
import java.io.*;
import java.net.*;
import java.io.BufferedReader;
// Variables declaration - do not modify
/**
*
* #author ****
*/
public class Client extends javax.swing.JFrame {
;
public Client() {
initComponents();
}
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
jTextField1.setText("");
input = jTextField1.getText();
send(input);
}
int port = 1234;
String hostname = "localhost";
String input,output;
public void send(String text) {
try {
Socket skt = new Socket(hostname, port); /*Connects to server*/
BufferedReader in = new BufferedReader(new
InputStreamReader(skt.getInputStream())); /*Reads from server*/
System.out.println("Server:" + in.readLine());
PrintWriter out = new PrintWriter(skt.getOutputStream(), true);
out.println(text); /*Writes to server*/
out.close(); /*Closes all*/
in.close();
skt.close();
}
catch(Exception e) {
System.out.print("Error Connecting to Server\n");
}
}
public void startUP() {
}
public static void main(String args[]) {
Client c = new Client();
c.startUP();
c.send("Server is online");
new Client().setVisible(true);
}
// Variables declaration - do not modify
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JTextField jTextField1;
// End of variables declaration
}
Server.java
package server;
import java.io.*;
import java.net.*;
class Server {
/*
To send string to client use "out.print(data)"
To use info sent from client use "in.readLine()"
*/
int port = 1234;
String input,output;
boolean e = false;
String question = "how are you";
String answer = "i am fine";
public void send(String text) {
ServerSocket srvr = null;
Socket skt = null;
PrintWriter out = null;
BufferedReader in = null;
try {
srvr = new ServerSocket(port);
skt = srvr.accept(); /*Waiting for Connection from client*/
System.out.println("Connection = true");
out = new PrintWriter(skt.getOutputStream(), true);
out.println(text); /*Write/Send to Client*/
in = new BufferedReader(new
InputStreamReader(skt.getInputStream())); /*Read from Client*/
System.out.println("Client:" + in.readLine());
input = in.readLine();
} catch( Exception e) {
System.out.println("Error Connecting\n");
} finally {
if(e == true){
try {
out.close();
in.close();
skt.close(); /*Closes all*/
srvr.close();
} catch (IOException e) {
}
}
}
}
public void testFor() {
if(input.equals(question)){ send(answer); }
}
public static void main(String args[]) {
Server s = new Server();
s.send("Client is online"); //sends a message to client
// s.testFor();
}
}

ok well to start of, to stop a while loop, at some point you have to say that statement is false or true (depending what u use in first place). so i.e if you say while(true). this will always be true as there is nothing to compare to therefore it will create infinite loop going on forever. however if you say we do something like that
`while(x=true)'
{
x=false;
}
this will ensure that you stop the while loop and you will not enter it again. How? well we enter the while loop under conditon that x is true. as soon as we enter that loop we declare x to be false. therefore on next iteration x will be false and as a result we will not enter while loop. Kinda straight forward isn't it ?
As of the problem it self, i suggest reading THIS article. It is very clear and nicely laid out and it will show you how to write good socket based program:)

1st question is to call the bufferreader, printwriter etc.. out of the methods then use the .close in a separate method which could be activated at any time.
for my 2nd question I found I can use a while loop:
while(true) {
//code...
}
Thanks for no one's help.

Related

Stopping java threads [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 4 years ago.
I wrote a java application for both Server and Client. What I want to do is stop the Client's application(and all of it's threads) when the user enters the word: "logout". I've tried everything I could find so kinda desperate here. Please send help!
Here is my code for Client.java
package client;
//Java implementation for multithreaded chat client
//Save file as Client.java
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client extends Thread
{
final static int ServerPort = 1234;
private volatile static boolean running = true;
public static void main(String args[]) throws UnknownHostException, IOException
{
Scanner scn = new Scanner(System.in);
// getting localhost ip
InetAddress ip = InetAddress.getByName("localhost");
// establish the connection
Socket s = new Socket(ip, ServerPort);
// obtaining input and out streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
// sendMessage thread
Thread sendMessage = new Thread(new Runnable()
{
#Override
public void run() {
while (running) {
// read the message to deliver.
try {
String msg = scn.nextLine();
if(msg == "logout") {
running = false;
dis.close();
dos.close();
scn.close();
s.close();
Thread.currentThread().interrupt();
break;
}
dos.writeUTF(msg);
}
catch (IOException e) {
if(!running) {
System.out.println("Closing...");
System.exit(0);
}
}
} }
});
// readMessage thread
Thread readMessage = new Thread(new Runnable()
{
#Override
public void run() {
while (running) {
// read the message sent to this client
try {
String msg = dis.readUTF();
if(sendMessage.isInterrupted()) {
running = false;
dis.close();
dos.close();
scn.close();
s.close();
Thread.currentThread().interrupt();
break;
}
System.out.println(msg);
} catch (IOException e) {
if(!running) {
System.out.println("Closing...");
System.exit(0);
}
}
}
}
});
sendMessage.start();
readMessage.start();
}
}
And this is my Server.java
package server;
//Java implementation of Server side
//It contains two classes : Server and ClientHandler
//Save file as Server.java
import java.io.*;
import java.util.*;
import java.net.*;
//Server class
public class Server
{
// Vector to store active clients
static Vector<ClientHandler> ar = new Vector<>();
// counter for clients
static int i = 0;
public static void main(String[] args) throws IOException
{
// server is listening on port 1234
ServerSocket ss = new ServerSocket(1234);
Socket s;
// running infinite loop for getting
// client request
while (true)
{
// Accept the incoming request
s = ss.accept();
System.out.println("New client request received : " + s);
// obtain input and output streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
System.out.println("Creating a new handler for this client...");
// Create a new handler object for handling this request.
ClientHandler mtch = new ClientHandler(s,"client " + i, dis, dos);
// Create a new Thread with this object.
Thread t = new Thread(mtch);
System.out.println("Adding this client to active client list");
// add this client to active clients list
ar.add(mtch);
// start the thread.
t.start();
// increment i for new client.
// i is used for naming only, and can be replaced
// by any naming scheme
i++;
}
}
}
//ClientHandler class
class ClientHandler implements Runnable
{
private String name;
final DataInputStream dis;
final DataOutputStream dos;
Socket s;
boolean isloggedin;
// constructor
public ClientHandler(Socket s, String name,
DataInputStream dis, DataOutputStream dos) {
this.dis = dis;
this.dos = dos;
this.name = name;
this.s = s;
this.isloggedin=true;
}
#Override
public void run() {
String received;
while (true)
{
try
{
// receive the string
received = dis.readUTF();
if(received.equals("logout")){
break;
}
// break the string into message and recipient part
StringTokenizer st = new StringTokenizer(received, "#");
String MsgToSend = st.nextToken();
String recipient = st.nextToken();
// search for the recipient in the connected devices list.
// ar is the vector storing client of active users
for (ClientHandler mc : Server.ar)
{
// if the recipient is found, write on its
// output stream
if (mc.name.equals(recipient) && mc.isloggedin==true)
{
mc.dos.writeUTF(this.name+" : "+MsgToSend);
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
try
{
// closing resources
this.dis.close();
this.dos.close();
this.s.close();
this.isloggedin=false;
}catch(IOException e){
e.printStackTrace();
}
}
}
Code reference: Multithread GroupChat 1
Multithread GroupChat 2
Don't compare Strings with == but with equals(). msg == "logout" Should be msg.equals("logout").

Simple java chat server that only broadcasts to other clients not sender

I have been working through a tutorial for a simple java chat server and would like to modify it so that it doesn't echo back to the original sender. I have tried to mod it with my limited skills but nothing I know has worked and any help would be appreciated.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
public class ChatServer {
// Port that the server listens on.
private static final int PORT = 9001;
// Creates names
private static HashSet<String> names = new HashSet<String>();
// Creates writers
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
// Main method, which just listens on a port and spawns handler threads.
public static void main(String[] args) throws Exception {
System.out.println("The Chatty server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
// Create character streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Request a name from this client. Keep requesting until
// a name is submitted that is not already used. Note that
// checking for the existence of a name and adding the name
// must be done while locking the set of names.
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
// Now that a successful name has been chosen, add the
// socket's print writer to the set of all writers so
// this client can receive broadcast messages.
out.println("NAMEACCEPTED");
writers.add(out);
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
// Where to add the section that prevents sending to original sender?
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
System.out.println(writer);
System.out.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException e) {
System.out.println(e);
} finally {
// This client is going down! Remove its name and its print
// writer from the sets, and close its socket.
if (name != null) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
Here is the client
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ChatClient {
BufferedReader in;
PrintWriter out;
JFrame frame = new JFrame("Chatty");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8, 40);
public ChatClient() {
// Layout GUI
textField.setEditable(false);
messageArea.setEditable(false);
frame.getContentPane().add(textField, "North");
frame.getContentPane().add(new JScrollPane(messageArea), "Center");
frame.pack();
// Add Listeners
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
out.println(textField.getText());
textField.setText("");
}
});
}
// Prompt for and return the desired screen name.
private String getName() {
return JOptionPane.showInputDialog(
frame,
"Choose a screen name:",
"Screen name selection",
JOptionPane.PLAIN_MESSAGE);
}
// Connects to the server then enters the processing loop.
private void run() throws IOException {
// Make connection and initialize streams
String serverAddress = "0";
Socket socket = new Socket(serverAddress, 9001);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Process all messages from server, according to the protocol.
while (true) {
String line = in.readLine();
if (line.startsWith("SUBMITNAME")) {
out.println(getName());
} else if (line.startsWith("NAMEACCEPTED")) {
textField.setEditable(true);
} else if (line.startsWith("MESSAGE")) {
messageArea.append(line.substring(8) + "\n");
}
}
}
// Runs the client as an application with a closeable frame.
public static void main(String[] args) throws Exception {
ChatClient client = new ChatClient();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setVisible(true);
client.run();
}
}
public class ChatServer {
// Port that the server listens on.
private static final int PORT = 9001;
// Creates names
private static HashSet<String> names = new HashSet<String>();
// Creates writers
private static HashMap<String,PrintWriter> writers = new HashMap<String,PrintWriter>();
// Main method, which just listens on a port and spawns handler threads.
public static void main(String[] args) throws Exception {
System.out.println("The Chatty server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
// Create character streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
String keyForEachUser = socket.getInetAddress().toString();
// Request a name from this client. Keep requesting until
// a name is submitted that is not already used. Note that
// checking for the existence of a name and adding the name
// must be done while locking the set of names.
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
// Now that a successful name has been chosen, add the
// socket's print writer to the set of all writers so
// this client can receive broadcast messages.
out.println("NAMEACCEPTED");
writers.put(keyForEachUser,out);
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
// Where to add the section that prevents sending to original sender?
for (String key : writers.keySet()) {
if (key.equalsIgnoreCase(keyForEachUser)) {
//original user founf not sending the data
}else{
PrintWriter writer = writers.get(key); //getting the correct output stream
writer.println("MESSAGE " + name + ": " + input);
System.out.println(writer);
System.out.println("MESSAGE " + name + ": " + input);
}
}
}
} catch (IOException e) {
System.out.println(e);
} finally {
// This client is going down! Remove its name and its print
// writer from the sets, and close its socket.
if (name != null) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
i have made some changes to your program , problem with your earlier code was that you cant identify users connected. now im using a hashmap object to store the printwriters and the key im using in hashmap is users inetaddress which is unique from pc to pc. maybe you should try this one

Java socket help debugging

I wrote a simple socket program but the sever is not printing out anything.
Client:
public class ChatClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 9001);
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
Scanner reader = new Scanner(System.in);
while (true) {
String test = reader.next();
out.write(test);
System.out.println(test);
//String line = in.readLine();
}
}
}
Server:
public class ServerApplication {
private static final int PORT = 9001;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
public static void main(String[] args) throws Exception {
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
System.out.println("Server starts!");
new ChatThread(listener.accept()).start();
}
} finally {
}
}
}
public class ChatThread extends Thread{
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public ChatThread(Socket socket){
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("Thread Starts!");
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
while(true){
System.out.println("Getting input!");
String input = in.readLine();
System.out.println("test");
if (input!=null){
//out.print(input);
System.out.println(input);}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Any ideas how should I fix this so when I type "Hello" on client, server will print out "Hello" using system.out.println()?
This is highly likely the socket buffers not being flushed and the data is not actually sent to the socket; the server is waiting for more data before sending a chunk.
If we look at the docs for PrintWriter:
... if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked ...
However, you are using print, not println, so the flushing is not automagic.
Try manualy flushing you streams after writing data:
out.write(test);
out.flush();
yep, this was an answer to a 3 year old post... question was edited and popped up on my stream
Testing your server using telnet (telnet localhost 9001) revealed that it's working just fine. I assume that the fact that it can only print a line at a time, rather than individual characters, is intended behavior.
I did find one bug. When terminating the telnet connection, the server would go into an infinite loop. I suggest the following change:
if (input!=null){
System.out.println(input);}
}
else {
break;
}
For the client, I was able to fix it simply by replacing write with println:
out.println(test);

A simple java client server program

So I did this client server program in java for my college mini project. Note that this is just a small module of a big project I'm working on. I need a string to be sent from the client to the server. The server will return back the string as it is back to the client. (The code will be modified later such that the string is processed before sending back). The client will send a string whenever needed to the server. Thus it means it is compulsory for the server to be running for indefinite time.
The problem I face here is that my server works perfectly only for the first time when the client sends a string. If I run the client the second time with a different string, I get back the same string I sent to the server previously!
Here is my server program:
public class Server {
public static boolean x = true;
public static String reply;
public static void main(String a[]) throws Exception {
System.out.println("Entered server console..");
Socket echoSocket = null;
ServerSocket serverSocket = null;
PrintWriter out = null;
BufferedReader in = null;
System.out.println("Initializing Connection..");
boolean runFlag = true;
try {
serverSocket = new ServerSocket(77);
while (runFlag) {
echoSocket = serverSocket.accept();
out = new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
while (x) {
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
reply = in.readLine();
if (reply != null) {
x = false;
}
}
System.out.println("received: " + reply);
out.println(reply);
System.out.println("sent back: " + reply);
stdIn.close();
}
} catch (Exception e) {
System.out.println("Exception in starting server: " + e.getMessage());
} finally {
out.close();
in.close();
echoSocket.close();
}
}
}
Here is my Client program:
public class Client {
public static String reply,temp;
public static boolean x=true;
public Client()
{
temp="lala";
}
public Client(String t)
{
temp=t;
}
public static void main(String[] args) throws IOException {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
echoSocket = new Socket("localhost", 77);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: localhost.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: localhost.");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
temp="lala"; //this is the string to be sent
out.println(temp);
while (x) {
reply= in.readLine();
if(reply!=null)
{
x=false;
}
}
System.out.println("reply: "+reply);
out.close();
in.close();
stdIn.close();
echoSocket.close();
}
}
Can anyone help me find what the problem here is?
while (x) {
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
reply = in.readLine();
if (reply != null) {
x = false;
}
}
Your server enters this loop the first time a client connects, and it sets the reply String to some input from the client. However, it never enters this loop again, as x's value never changes back to true.
When you accept a request, the x will be set false and never become true.
Please initial the x when you enter the loop.
What's more,if you use a socket between client and server, please move the
echoSocket = serverSocket.accept();
out of the first loop.And you can use echoSocket to communicate.Then you will
keep the long connection.

how to stop multithread chat client

I'm trying to create a multithread chat client-server using Java. I'm using this tutorial as a start: http://pguides.net/java-tutorial/java-tcp-clientserver-chat/
I want the client to stop when I enter the String "quit" but I don't understand how I could do it. Also, I need to remove the client from the connected nicks list when the client disconnects.
Server
/* ChatServer.java */
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Hashtable;
public class ChatServer {
private static int port = 1001;
public static void main (String[] args) throws IOException {
ServerSocket server = null;
try {
server = new ServerSocket(port);
} catch (IOException e) {
System.err.println("Could not listen on port: " + port);
System.err.println(e);
System.exit(1);
}
Socket client = null;
while(true) {
try {
client = server.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.err.println(e);
System.exit(1);
}
/* start a new thread to handle this client */
Thread t = new Thread(new ClientConn(client));
t.start();
}
}
}
class ChatServerProtocol {
private String nick;
private ClientConn conn;
private static Hashtable<String, ClientConn> nicks = new Hashtable<String, ClientConn>();
private static final String msg_OK = "OK";
private static final String msg_INVALID = "INVALID COMMAND";
private static final String msg_SEND_FAILED = "FAILED TO SEND";
private static boolean add_nick(String nick, ClientConn c) {
if (nicks.containsKey(nick)) {
return false;
} else {
nicks.put(nick, c);
return true;
}
}
private static boolean remove_nick(String nick, ClientConn c) {
if (!(nicks.containsKey(nick))) {
return false;
} else {
nicks.remove(nick);
return true;
}
}
public ChatServerProtocol(ClientConn c) throws IOException {
nick = null;
conn = c;
}
private boolean sendMsg(String recipient, String msg) {
if (nicks.containsKey(recipient)) {
ClientConn c = nicks.get(recipient);
c.sendMsg(nick + ": " + msg);
return true;
} else {
return false;
}
}
public String process(String msg) {
if (msg.startswith("Nick"){
String output = "";
if(add_nick(tryauthor, this.conn)) {
this.nick = tryauthor;
output = "Welcome "+tryauthor;
} else {
output = "Nick already in";
}
}
}
else if (msg.startsWith("msg")) {
String[] msg_parts = msg.split(":");
for(int i=0; i<msg_parts.length; i++){
System.out.println(msg_parts[i]);
}
String msg_type = msg_parts[0];
if(msg_type.equals("msg")) {
if(msg_parts.length < 3) output = msg_INVALID;
if(sendMsg(msg_parts[1], msg_parts[2])) output = msg_OK;
else output = msg_SEND_FAILED;
} else {
output = msg_INVALID;
}
}
return output;
}
}
class ClientConn implements Runnable {
private Socket client;
private BufferedReader in = null;
private PrintWriter out = null;
public ClientConn(Socket client) {
this.client = client;
try {
/* obtain an input stream to this client ... */
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
/* ... and an output stream to the same client */
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.err.println(e);
return;
}
}
public void run() {
String msg, response;
try {
ChatServerProtocol protocol = new ChatServerProtocol(this);
/* loop reading lines from the client which are processed
* according to our protocol and the resulting response is
* sent back to the client */
while ((msg = in.readLine()) != "quit\r\n") {
response = protocol.process(msg);
out.println("SERVER: " + response);
}
this.close();
} catch (IOException e) {
System.err.println(e);
}
}
public void sendMsg(String msg) {
out.println(msg);
}
public void close() throws IOException {
in.close();
out.close();
client.close();
}
}
Client
/* ChatClient.java */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ChatClient {
private static int port = 1001;
private static String host = "localhost";
private static BufferedReader stdIn;
public static void main (String[] args) throws IOException {
Socket server = null;
try {
server = new Socket(host, port);
} catch (UnknownHostException e) {
System.err.println(e);
System.exit(1);
}
stdIn = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(server.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
System.out.print("Nick: ");
String auth = stdIn.readLine();
out.println("Nick: " + auth);
String serverResponse = in.readLine();
System.out.println(serverResponse);
if (serverResponse.startsWith("SERVER: welcome")) {
/* create a thread to asyncronously read messages from the server */
ServerConn sc = new ServerConn(server);
Thread t = new Thread(sc);
t.start();
String msg;
/* loop reading messages from stdin and sending them to the server */
while ((msg = stdIn.readLine()) != "quit\r\n") {
out.println(msg);
}
sc.close();
System.out.println("Exit.");
System.out.println("---Client Error---");
}
else {
System.out.println("Exit.");
System.out.println("---Client Error---");
}
}
}
class ServerConn implements Runnable {
private BufferedReader in = null;
private Socket server;
public ServerConn(Socket s) throws IOException {
server = s;
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
public void run() {
String msg;
try {
/* loop reading messages from the server and show them
* on stdout */
while ((msg = in.readLine()) != "quit\r\n") {
System.out.println(msg);
}
this.close();
} catch (IOException e) {
System.err.println(e);
}
}
public void close() throws IOException {
in.close();
server.close();
}
}
Where and how should I close the connection?
now the client can be authenticated only if his name is part of a graph I've created before.
This seems to be written in the code. In your Process() method, you look for the author in the authorsgraph and if it is not found you return an error. Is this not what you intended? If the author is not found, should you add them instead? Maybe the add_nice() call should be in the else if you haven't found them along with some way to add the author to the authorsgraph?
Walking through the handling of a new connection in a debugger might help you here. Liberal use of System.out.println() messages might also be of service.
I want the client to stop when I enter the String "quit" but I don't understand how I could do it.
Well this code has a bug. You must use .equals() to check for String equality. != is only testing the msg doesn't have the same String reference, not the same string contents:
// can't use != on a `String` to check contents
while ((msg = stdIn.readLine()) != "quit\r\n") {
It should be:
while (true) {
msg = stdIn.readLine();
if (msg == null || msg.equals("quit")) {
break;
}
...
Notice also that I am not checking the "\r\n". The readLine() method returns the string (to quote from the javadocs) "not including any line-termination characters". Also, you should test against null in case the socket is closed. You also have 2 places in your client code with the same bug.
I need to remove the client from the connected nicks list when the client disconnects.
Your while loop above will exit if the client socket is closed or they enter "quit". You then call close(). After you call close() you could call protocol.remove_nicks() to remove him from the loop. But you don't have the "nick" String there.
Really, maintaining the list of nicks inside of the ChatServerProtocol may not be the right place for it. I would roll the ChatServerProtocol into the ClientConn class myself since there is one of each per connection. Either way some object needs to store the "nick" string that the author logged in with and then call remove_nick() with that string after "quit" is entered or the connection closes.
Lastly, use of HashTable has been deprecated since Java 5. I would use Collections.synchronizedMap(new HashMap<...>()) instead.
Hope this helps.
I want the client to stop when I enter the String "quit" but I don't understand how I could do it.
You can terminate the current Java programm immediately with System.exit(status). As the operating system automatically releases all resources (such as tcp sockets) acquired by a process when it terminates, that also closes your connection.
Also, I need to remove the client from the connected nicks list when the client disconnects.
That's harder. Keep in mind that a disconnect can happen for reasons other than the client terminating, for instance because the network cable is unplugged. That is, the client can not reliably inform the server that it is no longer there, the server must detect this itself. I would expect the tcp implementation of the server operating system to detect that the client is no longer there (how quickly is probably implementation dependent), and throw an exception to the application using that socket, which you can catch and remove the nick from the list.

Categories