Trying to build a simple multi-threaded chat server that runs via command prompt. The clients do connect to the server and the server will hold multiple clients, however when trying to send messages from one client to the other, or even notifying a client of another user logging in, nothing comes up on the client command prompt.
public class Server {
private static ServerSocket servSock;
private static Socket clientSock;
private static ArrayList<ClientThread> clientList;
private static int IDcount = 0;
public static void main(String args[]){
// Get command line arguments.
if (args.length != 3) {
System.out.println("Required arguments: server port, block duration, timeout");
return;
}
int port = Integer.parseInt(args[0]);
int blockDur = Integer.parseInt(args[1]);
int timeout = Integer.parseInt(args[2]);
try{
servSock = new ServerSocket(port);
clientList = new ArrayList<ClientThread>();
}
catch(IOException ex){
System.err.println(ex);
}
while (true) {
try {
clientSock = servSock.accept();
ClientThread thread = new ClientThread(clientSock);
clientList.add(thread);
thread.start();
} catch (IOException e) {
System.out.println(e);
}
}
}
private synchronized static void broadcast(String msg){
System.out.print(msg);
for(int i = 0; i < clientList.size(); i++){
ClientThread client = clientList.get(i);
client.send(msg);
}
}
synchronized static void unlist(int id){
for(int i = 0; i < clientList.size(); i++){
ClientThread thread = clientList.get(i);
if(thread.id == id){
clientList.remove(i);
return;
}
}
}
static class ClientThread extends Thread {
Socket sock;
BufferedReader tIn;
PrintWriter tOut;
int id;
String username;
String msg;
ClientThread(Socket sock){
id = IDcount++;
this.sock = sock;
try{
tIn = new BufferedReader(new InputStreamReader(sock.getInputStream()));
tOut = new PrintWriter(sock.getOutputStream());
username = tIn.readLine();
broadcast(username + " logged in");
}
catch(IOException ex){
System.err.println(ex);
}
}
public void run(){
boolean loggedIn = true;
while(loggedIn){
try{
msg = tIn.readLine();
}
catch (IOException ex){
System.err.println(ex);
}
String[] parts = msg.split("\\s",2);
String type = parts[0];
Client code is similar
public class Client{
private static Socket clientSock;
private static BufferedReader in;
private static PrintWriter out;
private static Scanner scan;
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.out.println("Required arguments: server IP, server port");
return;
}
String host = args[0];
int port = Integer.parseInt(args[1]);
clientSock = new Socket(host, port);
in = new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
out = new PrintWriter(clientSock.getOutputStream());
scan = new Scanner(System.in);
new ListenFromServer().start();
boolean online = true;
System.out.println("Enter your username:");
String username = scan.nextLine();
out.println(username);
while(online){
System.out.println("> ");
String msg = scan.nextLine();
String[] parts = msg.split("\\s");
String type = parts[0];
send(msg);
if(type.equalsIgnoreCase("logout")){
online = false;
}
}
logoff();
}
static void send(String msg) throws IOException{
out.println(msg);
}
private static void logoff() throws IOException{
in.close();
out.close();
scan.close();
clientSock.close();
}
static class ListenFromServer extends Thread{
public void run(){
while(true){
try{
String msg = in.readLine();
System.out.println(msg);
}
catch(IOException ex){
System.err.println(ex);
}
}
}
}
}
When you send data with PrintWriter.println(), data write to buffer. You must call PrintWriter.flush() after println to send data to or from the server immediately.
And when you call username = tIn.readLine(); in ClientThread constructor, you block main-thread, because constructor calls in main-thread. So, while connected user won't send username, other clients can't connect.
Related
I have this class where i try to create a number of threads and then i need to send a message to the server over all the threads or using a specific thread. I can't seem to find a way to do that in this way I can only send using the last thread that was created.
Here is the class:
public class test{
public test(){
}
public static void main(String[] args){
MultiThreadChatClient mc = new MultiThreadChatClient();
test st = new test();
for(int i =0; i<=4; i++){
mc.createThreads();
}
while (true) {
System.out.print("type your message: ");
Scanner s = new Scanner(System.in);
String ss = s.nextLine();
ss = ss.trim().replaceAll(" +", " ");
mc.sendMessage(ss);
try
{
Thread.sleep(400);
}
catch(InterruptedException e)
{
// this part is executed when an exception (in this example InterruptedException) occurs
System.out.println("Exeption: " + e);
}
}
}
}
Here's the Client thread class:
public class MultiThreadChatClient implements Runnable {
// The client socket
private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static BufferedReader br;
private static BufferedReader inputLine = null;
private static boolean closed = false;
public static void main(String[] args) {
// The default port.
int portNumber = 2222;
// The default host.
String host = "localhost";
if (args.length < 2) {
System.out.println("Usage: java MultiThreadChatClient <host> <portNumber>\n"
+ "Now using host=" + host + ", portNumber=" + portNumber);
} else {
host = args[0];
portNumber = Integer.valueOf(args[1]).intValue();
}
}
/*
* Open a socket on a given host and port. Open input and output streams.
*/
public void createThreads(){
try {
clientSocket = new Socket("localhost", 2222);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + 2222);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to the host " + 2222);
}
//}
/*
* If everything has been initialized then we want to write some data to the
* socket we have opened a connection to on the port portNumber.
*/
if (clientSocket != null && os != null && br != null) {
new Thread(new MultiThreadChatClient()).start();
}
}
public void sendMessage(String mes){
os.println(mes);
}
/*
* Create a thread to read from the server. (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run() {
/*
* Keep on reading from the socket till we receive "Bye" from the
* server. Once we received that then we want to break.
*/
String responseLine;
try {
while ((responseLine = br.readLine()) != null){
System.out.println(responseLine);
if (responseLine.indexOf("*** Bye") != -1)
break;
}
closed = true;
} catch (IOException e) {
System.err.println("IOException1234: " + e);
}
}
}
Here's the server code:
public class MultiThreadChatServerSync {
// The server socket.
private static ServerSocket serverSocket = null;
// The client socket.
private static Socket clientSocket = null;
// This chat server can accept up to maxClientsCount clients' connections.
private static final int maxClientsCount = 50;
private static final clientThread[] threads = new clientThread[maxClientsCount];
public static void main(String args[]) {
// The default port number.
int portNumber = 2222;
if (args.length < 1) {
System.out.println("Usage: java MultiThreadChatServerSync <portNumber>\n"
+ "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
/*
* Open a server socket on the portNumber (default 2222). Note that we can
* not choose a port less than 1023 if we are not privileged users (root).
*/
try {
serverSocket = new ServerSocket(portNumber);
//System.out.println(serverSocket.getPort());
} catch (IOException e) {
System.out.println(e);
}
/*
* Create a client socket for each connection and pass it to a new client
* thread.
*/
while (true) {
try {
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
//System.out.println("A new client is created");
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
class clientThread extends Thread {
MultiThreadChatServerSync ms = new MultiThreadChatServerSync();
private String clientName = null;
//private DataInputStream is = null;
private BufferedReader br = null;
private PrintStream os = null;
private Socket clientSocket = null;
private final clientThread[] threads;
private int maxClientsCount;
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
//System.out.println("Inside the Client thread");
}
public void run() {
MultiThreadChatServerSync mss = new MultiThreadChatServerSync();
int maxClientsCount = this.maxClientsCount;
clientThread[] threads = this.threads;
//System.out.println("Inside the run");
try {
/*
* Create input and output streams for this client.
*/
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
while (true) {
String line = br.readLine();
System.out.println("message received via Client port: " + clientSocket.getPort());
System.out.println("Received: " + line);
}
} catch (IOException e) {
}
}
}
So, is there a way to create 5 threads and then send the message over all of them or choose one specific thread out of them?
To be able to have a client which starts several sessions, and to be able to send data to one or several of them, the client must change in a few ways.
The static references in the client must be removed.
The Socket instances must be created and stored in the main thread (the writers will be used to send messages on behalf of one or more client sessions)
Each client session is now only responsible for reading (the reader is passed via the constructor).
The code is based on your original code, and meant to be a template for further enhancements: It will manage 5 client sessions, and be able to write to 1 or many.
The new main Thread (As an example, the Scanner will first ask the message for client #1, then 2, 3, 4 and next will broadcast to all, in a loop):
public class MultiThreadChatClientRunner {
final int NO_CLIENTS = 5;
//final String HOST_IP = "192.168.2.7";
final String HOST_IP = "localhost";
public static void main(String[] args) {
new MultiThreadChatClientRunner().start();
}
private void start() {
Socket[] sockets = new Socket[NO_CLIENTS];
PrintStream[] writers = new PrintStream[NO_CLIENTS];
BufferedReader[] readers = new BufferedReader[NO_CLIENTS];
for (int i = 0; i < NO_CLIENTS; i++) {
System.out.println("Creating client number "+i);
Socket clientSocket;
try {
clientSocket = new Socket(HOST_IP, 2222);
writers[i] = new PrintStream(clientSocket.getOutputStream());
readers[i] = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
new Thread(new MultiThreadChatClient(i, readers[i])).start();
} catch (IOException e) {
e.printStackTrace();
}
}
int clientId = 0;
Scanner s = new Scanner(System.in);
while (true) {
System.out.print("type your message for client #"+clientId);
String ss = s.nextLine();
ss = ss.trim().replaceAll(" +", " ");
writers[clientId].println(ss);
clientId = (clientId+1)%NO_CLIENTS;
// Test to broadcast to all clients
if (clientId == 4) {
for (int i = 0; i<NO_CLIENTS; i++)
writers[i].println("Broadcast message: "+ss);
}
try {
Thread.sleep(400);
} catch (InterruptedException e) {
System.out.println("Thread was interrupted");
break;
}
}
s.close();
}
}
The new client, which is much simpler than before:
public class MultiThreadChatClient implements Runnable {
// The client socket
private Socket clientSocket = null;
// The output stream
private PrintStream os = null;
// The input stream
private final BufferedReader br;
private final int clientId;
public MultiThreadChatClient(int clientId, BufferedReader br) {
super();
this.clientId = clientId;
this.br = br;
}
/*
* Create a thread to read from the server. (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run() {
/*
* Keep on reading from the socket till we receive "Bye" from the
* server. Once we received that then we want to break.
*/
String responseLine;
try {
while ((responseLine = br.readLine()) != null) {
System.out.printf("Client #%d received message=%s\n", clientId, responseLine);
if (responseLine.indexOf("*** Bye") != -1)
break;
}
} catch (IOException e) {
System.err.println("IOException1234: " + e);
}
}
}
And the server, which is nearly identical, but manages closes better, and has some more logging to show which client is communicating.
public class MultiThreadChatServerSync {
// The server socket.
private static ServerSocket serverSocket = null;
// The client socket.
private static Socket clientSocket = null;
// This chat server can accept up to maxClientsCount clients' connections.
private static final int maxClientsCount = 50;
private static final ClientThread[] threads = new ClientThread[maxClientsCount];
public static void main(String args[]) {
// The default port number.
int portNumber = 2222;
if (args.length < 1) {
System.out.println(
"Usage: java MultiThreadChatServerSync <portNumber>\n" + "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
/*
* Open a server socket on the portNumber (default 2222). Note that we
* can not choose a port less than 1023 if we are not privileged users
* (root).
*/
try {
serverSocket = new ServerSocket(portNumber);
// System.out.println(serverSocket.getPort());
} catch (IOException e) {
System.out.println(e);
}
/*
* Create a client socket for each connection and pass it to a new
* client thread.
*/
while (true) {
try {
System.out.println("Awaiting a new connection on "+serverSocket.getLocalPort());
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new ClientThread(i, clientSocket)).start();
// System.out.println("A new client is created");
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
class ClientThread extends Thread {
private BufferedReader br = null;
private PrintStream os = null;
private final Socket clientSocket;
private final int clientId;
public ClientThread(int clientId, Socket clientSocket) {
this.clientSocket = clientSocket;
this.clientId = clientId;
}
public void run() {
try {
/*
* Create input and output streams for this client.
*/
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
String line = "";
while ((line = br.readLine()) != null) {
System.out.printf("Client <%d> received message=<%s> via Client port: <%d>\n", clientId, line, clientSocket.getPort());
// Echo it back (as a test)
os.println(line);
}
br.close();
os.close();
clientSocket.close();
} catch (IOException e) {
}
System.out.println("Client has closed the session");
}
}
Let me know if you have any further questions at this time.
So I've been making a chatroom based off a single server, where clients can connect and talk in the chatroom. At the moment each client can speak to the server and the server returns what the client has said. But I've been struggling to broadcast a single client message to all clients.
I stored all socket connections in an ArrayList and then created a for loop to iterate through all the connections to echo a single message to all the connected clients. Unfortunately my code is not working and I can't understand why. Here's my code:
Handler code:
public class Handler implements Runnable {
private Socket client;
String message = "";
public Handler(Socket client){
this.client = client;
}
#Override
public void run() {
try{
try{
ChatClient CCG = new ChatClient();
Scanner INPUT = new Scanner(client.getInputStream()); //input data from the server
PrintWriter OUT = new PrintWriter(client.getOutputStream()); //output data from the server
while(true){
if(!INPUT.hasNextLine()){ //if nothings there, end it
return;
}
message = INPUT.nextLine(); //get input
System.out.println("Client HANDLER said: "+ message);
//echo out what the client says to all the users
for(int i=1; i<= ChatServer.ConnectionArray.size(); i++){
Socket TEMP_SOCK = (Socket) ChatServer.ConnectionArray.get(i-1);
PrintWriter TEMP_OUT = new PrintWriter(TEMP_SOCK.getOutputStream());
TEMP_OUT.println(message);
TEMP_OUT.flush();
System.out.println("Sent to: " + TEMP_SOCK.getLocalAddress().getHostName()); //displyed in the console
}
}
}finally{
client.close();
}
}catch(Exception X){
X.printStackTrace();
}
}
}
EDIT: Changed client.getOutputStream() to TEMP_SOCK.getOutputStream() but still no luck :/
Server code:
public class ChatServer {
public static ServerSocket server;
public static boolean ServerOn=true;
public static ArrayList<Socket> ConnectionArray = new ArrayList<Socket>(); //holds all the connections so messages can be echoed to all the other users
public static ArrayList<String> CurrentUsers = new ArrayList<String>(); //current users
public static void main(String[] args){
//ExecutorService executor = Executors.newFixedThreadPool(30); //number of clients allowed to join the server
try {
server = new ServerSocket(14001);
System.out.println("Server started!");
System.out.println("Waiting for clients to connect...");
while(true){
try {
//ChatClient chatClient = new ChatClient();
Socket client = server.accept();
ConnectionArray.add(client); //add socket to connection array and allows multiple users to enter server
System.out.println(ConnectionArray);
//CurrentUsers.add(chatClient.user);
//System.out.println("Current users: "+CurrentUsers);
System.out.println("Client connected from: " + client.getLocalAddress().getHostName()); //gets their ip address and local host name
Thread thread = new Thread(new Handler(client));
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Client Code:
public class ChatClient extends javax.swing.JFrame {
Socket sock;
String message;
int port = 14001;
PrintWriter write;
BufferedReader read;
String user;
ArrayList<String> usersOnline = new ArrayList();
InputStreamReader streamreader;
boolean userConnected = false;
public ChatClient() {
initComponents();
}
/*public class Incoming implements Runnable{
public void run(){
try{
sock = new Socket("localhost",14001);
write = new PrintWriter(out);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}*/
public void addUser(){
onlineUsersTextArea.append(user+" \n");
usersOnline.add(user);
System.out.println(usersOnline);
}
/*public void Send(){
String bye = (user + ": :Disconnect");
try{
write.println(bye);
write.flush();
}catch(Exception ex){
chatTextArea.append("Could not send disconnect message. \n");
}
}*/
public void userDisconnected(){
chatTextArea.append(user + " has disconnected.\n");
}
public void Disconnect(){
try{
chatTextArea.append("Disconnected.\n"); // Notify user that they have disconnected
write.flush();
sock.close(); // Closes the socket
System.out.println(user + " has disconnected.");
}catch(Exception e){
chatTextArea.append("Failure to disconnect.\n");
}
userConnected = false;
onlineUsersTextArea.setText(""); // Remove name from online users
usernameInputField.setEditable(true); // Allows a username to be created
}
private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {
if(userConnected == false){
user = usernameInputField.getText();
usernameInputField.setEditable(false);
try{
sock = new Socket("localhost", port);
InputStreamReader sReader = new InputStreamReader(sock.getInputStream());
write = new PrintWriter(sock.getOutputStream());
read = new BufferedReader(sReader);
addUser();
chatTextArea.append(user + " has connected. \n");
write.println(user+" has connected."); // Display username of client when connection is established
write.flush(); // Flushes the stream
userConnected = true;
} catch (IOException ex) {
chatTextArea.append("Failed to connect.\n");
usernameInputField.setEditable(true);
ex.printStackTrace();
}
}else if(userConnected == true){
chatTextArea.append("You are already connected. \n");
}
}
private void disconnectButtonActionPerformed(java.awt.event.ActionEvent evt) {
Disconnect();
userDisconnected();
}
private void sendButtonActionPerformed(java.awt.event.ActionEvent evt) {
String nothing = "";
if((userInputTextArea.getText()).equals(nothing)){
userInputTextArea.setText("");
userInputTextArea.requestFocus();
}else{
try{
chatTextArea.append(user + ": " + userInputTextArea.getText()+" \n");
write.println(user + ": " + userInputTextArea.getText());
write.flush();
}catch(Exception ex){
chatTextArea.append("Message failed to send. \n");
}
userInputTextArea.setText("");
userInputTextArea.requestFocus();
}
userInputTextArea.setText("");
userInputTextArea.requestFocus();
}
private void usernameInputFieldActionPerformed(java.awt.event.ActionEvent evt) {
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ChatClient().setVisible(true);
}
});
}
}
My for loop is in the Handler class. I'm not understanding why the message isn't being sent out to the clients. The TEMP_SOCK (temporary socket) should work (I think) but the server only receives the messages but doesn't echo them.
Any help on how to go about this would be really appreciated! Thank you :)
PrintWriter TEMP_OUT = new PrintWriter(client.getOutputStream()); means you're always sending to the same client, you should use PrintWriter TEMP_OUT = new PrintWriter(TEMP_SOCK.getOutputStream());
I'm trying to create a java push server model for testing on my own machine, this won't be used to connect external clients as the server and client will be on the same machine. After the client connects on the port specified by he/she, they should send a message of their choice that will be sent back to them, and any other clients connected to the same port.
The problem I'm having is i receive a java.net.ConnectException: Connection refused: connect when this is attempted. Below is the client and the server.
Edit: I've taken the time to ensure that the necessary ports are open too, and even disabled my firewall, but to no avail.
Server:
class MainServer {
// port that oir server is going to operate on
final static int port = 1234;
public static void main(String[] args) {
// this is going to model the server for the moment
System.out.println("Server has been started...");
Buffer<Messages> store = new Buffer<Messages>(10);
new Writer(store).start();
try {
ServerSocket serve = new ServerSocket(port);
while(true) {
// wait for server request
Socket socket = serve.accept();
// start thread to service request
new ServerThread(socket,store).start();
}
} catch(IOException e) {e.printStackTrace();}
}
}
class ServerThread extends Thread {
Socket socket;
Buffer<Messages> buffer;
public ServerThread(Socket s, Buffer<Messages> b) {
socket = s;buffer = b;
}
public void run() {
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
int port = in.readInt();
System.out.println("Port: "+port);
Messages ms = new Messages(port);
// Read message as string from user
String message = in.readUTF();
int k = in.readInt();
while(k != -1) {
// Add message to array
// read next message
ms.add(message);
message = in.readUTF();
}
// close connection
socket.close();
// add message to buffer
buffer.put(ms);
} catch(IOException e) {e.printStackTrace();}
}
}
class Writer extends Thread {
Buffer<Messages> buffer;
public Writer(Buffer<Messages> m) {buffer = m;}
public void run() {
while(true) {
Messages dp = buffer.get();
dp.write();
}
}
}
class Buffer <E> {
/**
* Producer & Consumer Buffer
*/
private int max;
private int size = 0;
private ArrayList<E> buffer;
private Semaphore empty; //control consumer
private Semaphore full; // control producer
private Lock lock = new ReentrantLock();
public Buffer(int s) {
buffer = new ArrayList<E>();
max = s;
empty = new Semaphore(0);
full = new Semaphore(max);
}
// add data to our array
public void put(E x) {
try {
full.acquire();
} catch(InterruptedException e) {}
// sync update to buffer
lock.lock();
try {
buffer.add(x);
size++;
empty.release();
} finally {lock.unlock();}
}
public E get() {
try {
empty.acquire();
} catch(InterruptedException e) {}
// sync uodate on buffer
lock.lock();
try {
E temp = buffer.get(0);
buffer.remove(0);
size--;
full.release();
return temp;
} finally {lock.unlock();}
}
}
final class Messages {
private final int port;
private final ArrayList<String> data = new ArrayList<String>();
public Messages(int p) {port = p;}
void add(String message) {
data.add(message);
}
void write() {
try {
Socket socket;
socket = new Socket(InetAddress.getLocalHost(),port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// write message
out.write(data.size());
for(String k : data) {out.writeUTF(k);}
out.flush();
socket.close();
} catch(IOException e) {e.printStackTrace();}
}
}
Client:
class Client {
final static int nPort = 1234;
static int serverPort;
public static void main(String[] args) {
// this class and those present in it
// will model the client for assignment 8
Scanner in = new Scanner(System.in);
System.out.println("Please enter the messageboard number: ");
serverPort = in.nextInt();
System.out.println("Please type your message: ");
String msg = in.next();
Listener lis = new Listener(serverPort);
lis.start();
boolean go = true;
while(go) {
try {
Thread.sleep(2000);
} catch(InterruptedException e) {}
write(serverPort, msg);
System.out.println("Continue: 0/1");
int x = in.nextInt();
if(x == 0)go = false;
}
System.exit(0);
}
static void write(int port, String msg) {
try {
Socket socket;
socket = new Socket(InetAddress.getLocalHost(),port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// send message to port
out.writeInt(port);
out.writeUTF(msg);
// write sentinal after message has been written and close socket
out.writeInt(-1);
out.flush();
socket.close();
} catch(IOException e) {System.out.println(e);}
}
}
class Listener extends Thread {
private int port;
volatile boolean go;
public Listener(int p) {p = port;}
public void run() {
try {
ServerSocket serversock = new ServerSocket(port);
while(go) {
Socket socket = serversock.accept();
DataInputStream in = new DataInputStream(socket.getInputStream());
// Read the message
while(in.available() > 0) {
String k = in.readUTF();
System.out.print(k+" ");
}
System.out.println();
socket.close();
}
} catch(IOException e) {go = false;}
}
}
Turns out i had a wrong assignment in my Listener class. I had p = port instead of port = p.
Solved. Through my own stupidity.
The hostname you are connecting to is localhost so you are assuming the server is on the same machine. If you need to connect to a different machine, you need to specify the host you want it to connect to.
Try changing socket = new Socket(InetAddress.getLocalHost(),port);
to
socket = new Socket(*IP OF SERVER (127.0.0.1 if same machine)*, port);
I am writing a Server/Client chat where basically Multiple Clients connected to One Server. One client send a message to server Then all other Clients will get the same message. For example: Client A, B, C Connected to A same Server. Client A send Message To Server, Server then will send the same message to client B and C but exclude Client A.
I'm stuck at part where Server send out the message to all other clients.
Below is the code, I'm just a Java beginner so any help with the code will be much appreciate.
ServerSide
public class ServerP2P extends Thread{
private ServerSocket server = null;
private Socket clientSocket = null;
private ArrayList<ServerThread> clientThreadList = new ArrayList<>();
private int maxClient = 4;
private int port = 9990;
boolean listening = true;
public ServerP2P(){
try{
server = new ServerSocket(port);
}catch(IOException e){
e.printStackTrace();
return;
}
System.out.println("Server with Port "+port+" is Up and Running");
}
public void run(){
System.out.println("Room Chat Is Up");
while(listening){
for(int i = 0;i<clientThreadList.size();i++){
if(!clientThreadList.get(i).getConneection()){
System.out.println(clientThreadList.get(i)+" is removing from server because there is no conntection");
clientThreadList.remove(i);
}
}
try{
clientSocket = server.accept();
}catch(Exception e){
e.printStackTrace();
}
System.out.println("User with IP "+clientSocket.getInetAddress()+" Has Connected to Server");
clientThreadList.add(new ServerThread(clientSocket));
try{
Thread.sleep(200);
}catch(Exception e){
e.printStackTrace();
}
}
}
public ArrayList<ServerThread> listOFClient(){
return clientThreadList;
}
public static void main(String[] args){
ServerP2P server = new ServerP2P();
server.start();
}
}
ServerThread
public class ServerThread{
private Socket clientSocket;
private boolean connected;
private Incomming incommingData;
String msg = null;
private class Incomming extends Thread{
private DataInputStream input;
public void run(){
try{
input = new DataInputStream(clientSocket.getInputStream());
}catch(IOException e){
e.printStackTrace();
return;
}
System.out.println("User with IP "+clientSocket.getInetAddress()+" has connected");
while(true){
try{
Thread.sleep(200);
int msgSize = input.readInt();
byte[] msgByte = new byte[msgSize];
for(int i = 0; i < msgSize ; i++){
msgByte[i] = input.readByte();
}
msg = new String(msgByte);
System.out.println(msg);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public ServerThread(Socket newClientSocket){
this.clientSocket = newClientSocket;
connected = true;
incommingData = new Incomming();
incommingData.start();
}
public boolean getConneection(){
return connected;
}
public void closeConnection(){
try{
connected = false;
clientSocket.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
ClientSide
public class ClientP2P{
private Socket serverSocket = null;;
private DataOutputStream output = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
public static void main(String[] args) {
ClientP2P client = new ClientP2P();
client.startConnect();;
}
public void startConnect(){
int port = 9990;
try {
serverSocket = new Socket("localhost", port);
System.out.println(serverSocket.isBound());
output = new DataOutputStream(serverSocket.getOutputStream());
System.out.println("Please Enter Your name: ");
String nameClient = reader.readLine();
output.writeInt(nameClient.length());
output.writeBytes(nameClient);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("You Are Connected");
System.out.println("Chat Can Start");
sendText();
}
public void sendText(){
try {
while (true) {
System.out.println("Type Message: ");
String msg = reader.readLine();
output.writeInt(msg.length());
output.writeBytes(msg);
System.out.println("Message sent");
recivedText();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void recivedText(){
try{
DataInputStream input = new DataInputStream(serverSocket.getInputStream());
int textSize = 0;
while(input.available() != 0){
byte[] byteString = new byte[textSize];
for(int i = 0; i < textSize;i++){
byteString[i] = input.readByte();
}
String txtServer = new String(byteString);
System.out.println(txtServer);
textSize = 0;
}
sendText();
}catch(Exception e){
e.printStackTrace();
}
}
}
Thanks For Your Time Guys.
Your ServerThread receives the messages and you want to send them to all other clients. One way you could achieve is to have the clients register themselves with the Server (this would help in the server not knowing the clients when it starts, which ideally should be the case). In your ServerThread, get a list of available clients from the server and loop through them and send the message to each one of them.
Use ObserverDesign pattern to hold the list of all your buddy/user to whom you wish to send message. Use HashMap to maintain a list of all the observer and its socket. Once the message is received, you retrieve the sockets of each user and write the same message on each socket.
I'm trying to create a very simple chat application in Java using UDP sockets. There is one server and multiple clients.
right now my code is :
Server :
package chat;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Set;
class User{
InetAddress addr;
int port;
User(InetAddress a,int p){
addr = a;
port = p;
}
}
public class Server {
private static final int PORT = 27012;
private static DatagramSocket sckt;
private static DatagramPacket in,out;
private static byte[] buffer;
private static HashMap<String,User> users;
public static void main(String[] args) {
try{
System.out.println("Opening port...");
sckt = new DatagramSocket(PORT);
users = new HashMap<String,User>();
}
catch(SocketException e){
System.out.println("Port connection failed!");
System.exit(1);
}
handleClient();
}
private static void sendMsg(InetAddress addr, int port, String msg){
try{
out = new DatagramPacket(msg.getBytes(),msg.length(),addr,port);
sckt.send(out);
}catch(IOException e){
e.printStackTrace();
}
}
private static void handleClient(){
try{
String msgIn,msgOut="",senderNick;
do{
buffer = new byte[256];
in = new DatagramPacket(buffer,buffer.length);
sckt.receive(in);
InetAddress clientAddress = in.getAddress();
int clientPort = in.getPort();
msgIn = new String(in.getData(),0,in.getLength());
//print msgIn
//System.out.println(msgIn);
senderNick = msgIn.substring(0,msgIn.indexOf(" "));
msgIn = msgIn.substring(msgIn.indexOf(" ")+1);
if(msgIn.equals("/connect")){
//String nick = msgIn.substring(msgIn.indexOf(" ") + 1);
System.out.println(senderNick);
if(users.containsKey(senderNick)){
msgOut = "Nick already in use!";
}
else{
users.put(senderNick, new User(clientAddress,clientPort));
msgOut = "Connected!";
}
sendMsg(clientAddress,clientPort,msgOut);
}
else if(msgIn.equals("/list")){
Set userNames;
userNames = users.keySet();
msgOut = "Users : \n";
msgOut += userNames.toString();
sendMsg(clientAddress,clientPort,msgOut);
}
else if(msgIn.startsWith("/msg")){
String tmp = msgIn.substring(msgIn.indexOf(" ")+1);
String receiverName = tmp.substring(0,tmp.indexOf(" "));
String message = tmp.substring(tmp.indexOf(" ")+1);
if(!users.containsKey(receiverName)){
msgOut = "User " + receiverName + " not found!";
sendMsg(clientAddress,clientPort,msgOut);
}
else{
User receiver = users.get(receiverName);
msgOut = "Message from "+ senderNick +" : "+message;
sendMsg(clientAddress,clientPort,"Message Sent!");
sendMsg(receiver.addr,receiver.port,msgOut);
}
}
else if(msgIn.startsWith("/nick")){
String newNick = msgIn.substring(msgIn.indexOf(" ")+1);
if(users.containsKey(newNick)){
msgOut = "Nick already in use!";
}
else{
users.put(newNick,users.get(senderNick));
users.remove(senderNick);
msgOut = "Nick changed!";
}
sendMsg(clientAddress,clientPort,msgOut);
}
else if(msgIn.equals("/disconnect")){
users.remove(senderNick);
}
//out = new DatagramPacket(msgOut.getBytes(),msgOut.length(),clientAddress,clientPort);
//sckt.send(out);
}while(true);
}
catch(IOException e){
e.printStackTrace();
}
finally{
System.out.println("Closing connection.");
sckt.close();
}
}
}
Client :
package chat;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
private static InetAddress host;
private static final int PORT = 27012;
private static DatagramSocket sckt;
private static DatagramPacket in, out;
private static byte[] buffer;
private static String nick;
static class MessageListener implements Runnable {
//DatagramPacket in;
//byte[] buffer;
String reply;
public void run() {
do{
try{
buffer = new byte[256];
in = new DatagramPacket(buffer,buffer.length);
sckt.receive(in);
reply = new String(in.getData(),0,in.getLength());
System.out.println("SERVER> "+reply);
}
catch(IOException e){
e.printStackTrace();
}
}while(true);
}
}
public static void main(String[] args) {
try {
host = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
System.out.println("Host not found!");
System.exit(1);
}
connect();
}
private static void sendMsg(String msg) {
try {
out = new DatagramPacket(msg.getBytes(), msg.length(), host, PORT);
sckt.send(out);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void connect() {
Scanner sc = new Scanner(System.in);
try {
buffer = new byte[256];
sckt = new DatagramSocket();
String reply = "";
do {
System.out.println("Name: ");
nick = sc.nextLine();
sendMsg(nick + " /connect");
in = new DatagramPacket(buffer, buffer.length);
sckt.receive(in);
reply = new String(in.getData(), 0, in.getLength());
System.out.println("SERVER> " + reply);
} while (!reply.equals("Connected!"));
accessServer();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void accessServer() {
try {
sckt = new DatagramSocket();
Scanner sc = new Scanner(System.in);
String msg = "", reply = "";
Thread myT = new Thread(new MessageListener());
myT.start();
do {
System.out.print("Enter Message: ");
msg = sc.nextLine();
if (!msg.equals("/quit")) {
buffer = new byte[256];
sendMsg(nick + " " + msg);
} else {
sendMsg(nick + " /disconnect");
}
} while (!msg.equals("/quit"));
sc.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Connection closing...");
sckt.close();
}
}
}
I want to be able to send a message to a single user or to all the users but the problem is that i can't receive the message on the client because as it stands now the client only receives a message after it sends one to the server. So my thought was to use a thread that continuosly listens for messages from the server but it doesn't work. What's the easiest way to go about this ?
You are attempting to use the received datagram immediately, instead of waiting for the thread you created to receive a datagram and populate your in variable. You could either handle the received datagram directly in the thread's code, or signal the main thread when a datagram is received using a wait() / notify() scheme.