Currently I'm working on this mini chat program in Java where multiple users should be able to log into the chat program and chat. Right now what my program does is log in users (Clients) to the Server, and what ever they say gets echoed back by the Server. What I want to do is be able to send a request to chat with another client directly.
My idea was to create a Hash map that holds the username of the client and its socket. When a client requests to chat with another client it looks for that user's username in the HashMap and if the other client agrees to chat then it connects the sockets.
I'm not sure how to implement this and also my program only takes one input from the user and returns it from the Server and after that it stops I have no idea why. I've been trying to get this working for a while now, starting to give me headaches.
Here's the code:
Client Class:
package source;
import java.io.*;
import java.util.*;
import java.net.*;
public class Client implements Runnable {
private Socket socket;
private DataOutputStream dout;
private DataInputStream din;
// Constructor
public Client() {
// Code
}
public Client(String host, int port) {
try {
socket = new Socket(host, port);
System.out.println("connected to " + socket);
din = new DataInputStream(socket.getInputStream());
dout = new DataOutputStream(socket.getOutputStream());
new Thread(this).start();
} catch (IOException ie) {
System.out.println(ie);
}
}
private void processMessage(String message) {
try {
dout.writeUTF(message);
} catch (IOException ie) {
System.out.println(ie);
}
}
public void run() {
try {
while (true) {
String message = din.readUTF();
System.out.println(message);
}
} catch (IOException ie) {
System.out.println(ie);
}
}
public static void main(String[] args) throws IOException {
while (true) {
String prompt;
Scanner clientPrompt = new Scanner(System.in);
System.out.println("client> ");
prompt = clientPrompt.next();
if (prompt.equals("Emmanuel"))
System.out.println("God With Us");
else if (prompt.equals("goOnline")) {
// Enter a host name
// Enter a portNumber
// Enter a userName
String h, p, u;
System.out.println("Enter hostname: ");
h = clientPrompt.next();
System.out.println("Enter portNumber: ");
p = clientPrompt.next();
System.out.println("Enter userName: ");
u = clientPrompt.next();
goOnline(h, p, u);
} else if (prompt.equals("Exit")) {
clientPrompt.close();
System.exit(1);
} else {
System.out.println("Invalid Input, Try Again");
}
}
}
public static void goOnline(String host, String port, String userName) {
int portNumber = Integer.parseInt(port);
Client c = new Client(host, portNumber);
c.processMessage("Username: " + userName);
String prompt;
Scanner clientPrompt = new Scanner(System.in);
while (true) {
prompt = clientPrompt.next();
c.processMessage(prompt);
c.run();
if (prompt.equals("Exit")) {
System.out.println("Bye Bye");
clientPrompt.close();
}
}
}
}
Server Class:
package source;
import java.io.*;
import java.net.*;
import java.util.*;
public class Server { // The ServerSocket we'll use for accepting new
// connections
private ServerSocket ss;
private HashMap<String, Socket> userInfo = new HashMap<String, Socket>();
// A mapping from sockets to DataOutputStreams.
private Hashtable<Socket, DataOutputStream> outputStreams = new Hashtable<Socket, DataOutputStream>();
// Constructor and while-accept loop all in one.
public Server(int port) throws IOException {
// All we have to do is listen
listen(port);
}
private void listen(int port) throws IOException {
// ServerSocket
ss = new ServerSocket(port);
System.out.println("Listening on " + ss);
while (true) {
Socket s = ss.accept();
System.out.println("Connection from " + s);
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
DataOutputStream userInfo = new DataOutputStream(s.getOutputStream());
outputStreams.put(s, dout);
outputStreams.put(s, userInfo);
new ServerThread(this, s);
}
}
Enumeration<DataOutputStream> getOutputStreams() {
return outputStreams.elements();
}
void sendToAll(String message) {
for (Enumeration<DataOutputStream> e = getOutputStreams(); e.hasMoreElements();) {
// Output Stream
DataOutputStream dout = (DataOutputStream) e.nextElement();
// Send Message
try {
dout.writeUTF(message);
} catch (IOException ie) {
System.out.println(ie);
}
}
}
// Remove socket,
void removeConnection(Socket s) {
// Synchronize
synchronized (outputStreams) {
// Tell the world
System.out.println("Removing connection to " + s);
// Remove it from hashtable
outputStreams.remove(s);
try {
s.close();
} catch (IOException ie) {
System.out.println("Error closing " + s);
ie.printStackTrace();
}
}
}
void addInfo(String user, Socket s) {
userInfo.put(user, s);
}
// Main
static public void main(String args[]) throws Exception {
// Get port
int port = Integer.parseInt(args[0]);
// Create Server object
new Server(port);
}
}
ServerThread:
package source;
import java.io.*;
import java.util.*;
import java.net.*;
public class ServerThread extends Thread { // The Server that spawned us
private Server server;
private Socket socket;
public ServerThread(Server server, Socket socket) {
this.server = server;
this.socket = socket;
start();
}
public void run() {
try {
DataInputStream din = new DataInputStream(socket.getInputStream());
while (true) {
String message = din.readUTF();
StringTokenizer stt = new StringTokenizer(message, " ");
while (stt.hasMoreTokens()) {
String token = stt.nextToken();
if (token.equals("Username:")) {
String username = stt.nextToken();
server.addInfo(username, socket);
}
}
System.out.println("Sending " + message);
server.sendToAll(message);
if (message.equals("Exit")) {
System.out.println("Bye Bye");
server.removeConnection(socket);
System.exit(1);
}
}
} catch (EOFException ie) {
} catch (IOException ie) {
ie.printStackTrace();
} finally {
server.removeConnection(socket);
}
}
}
my program only takes one input from the user and returns it from the Server and after that it stops I have no idea why?
Just do one change as mentioned below at client side to resolve above issue.
public void run() {
try {
// while (true) { // remove an infinite loop that will block
// the client thread to accept next message
String message = din.readUTF();
System.out.println(message);
// }
} catch (IOException ie) {
System.out.println(ie);
}
}
Doubt: (client side)
You have started a thread then why are you calling run() method directly.
Related
Basically I'm writing a 2 way communication client server program. The client sends requests to the server and server responds accordingly. The requests have to do with adding or removing tokens from a list of tokens stored on the server. The client side seems to work fine, the requests are being sent to the server. However it seems that the server is not receiving any request from the client and I have no idea why. I've attached the code:
client
package;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class TokenClient {
private static final int PORT_NUMBER = 9999;
private Socket socket;
private InputStream inStream;
private OutputStream outStream;
private Scanner inStreamScanner;
private PrintWriter outStreamPrinter;
public static void main(String[] args) {
new TokenClient().go();
}
void go() {
try {
System.out.println(
"Enter commands of the form \"CONNECT IP-address\", \"SUBMIT token\", \"REMOVE token\" or \"QUIT\"\n");
Scanner consoleScanner = new Scanner(System.in);
// java.io.BufferedReader consoleInputReader = new
// BufferedReader(new InputStreamReader(System.in));
String command = "";
while (!command.equals("QUIT") && consoleScanner.hasNextLine()) {
command = consoleScanner.nextLine(); // consoleInputReader.readLine();
processCommand(command);
}
System.out.println("Goodbye!");
consoleScanner.close();
} catch (IOException e) {
System.out.println("An exception occurred: " + e);
e.printStackTrace();
}
}
void processCommand(String userCommand) throws IOException {
if (userCommand.startsWith("SUBMIT"))
sendMessageToServer(userCommand);
else if (userCommand.startsWith("REMOVE"))
sendMessageToServer(userCommand);
else if (userCommand.equals("QUIT"))
closeConnectionToServer();
else if (userCommand.startsWith("CONNECT")) {
closeConnectionToServer();
connectToServer(userCommand);
} else
System.out.println("Invalid user command: " + userCommand);
}
void closeConnectionToServer() {
if (socket != null && !socket.isClosed()) {
try {
System.out.println("Disconnecting from server...");
sendMessageToServer("QUIT");
socket.close();
System.out.println("Connection to server closed.");
} catch (IOException e) {
System.out.println("An exception occurred: " + e);
e.printStackTrace();
}
}
}
void connectToServer(String connectCommand) throws IOException {
String ipAddress = connectCommand.substring(8).trim();
System.out.println("Connecting to server at " + ipAddress + ", port " + PORT_NUMBER + "...");
socket = new Socket(ipAddress, PORT_NUMBER);
inStream = socket.getInputStream();
outStream = socket.getOutputStream();
inStreamScanner = new Scanner(inStream);
outStreamPrinter = new PrintWriter(outStream);
System.out.println("Connected to server.");
}
void sendMessageToServer(String command) {
System.out.println("Sending message to server: " + command + "...");
if (socket == null || socket.isClosed())
System.out.println("Not possible - not connected to a server");
else {
outStreamPrinter.println(command); // send the message to the server
// NB: client doesn't check if tokens are valid
outStreamPrinter.flush(); // do so immediately
// Receive response from server:
if (!command.equals("QUIT") && inStreamScanner.hasNextLine()) {
String response = inStreamScanner.nextLine();
System.out.println("Response from server: " + response);
}
}
}
}
server
package;
import java.net.*;
import java.util.ArrayList;
import java.util.Scanner;
import java.io.*;
public class server {
private static Socket s;
private static Scanner inStreamScanner;
private static int PORT_NUMBER = 9999;
private static InputStream inStream;
private static OutputStream outStream;
private static PrintWriter outStreamPrinter;
private static ArrayList<String> ts = new ArrayList<String>();
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(PORT_NUMBER);
server serverInstance = new server();
server.s = ss.accept();
System.out.println("Client connected");
inStream = s.getInputStream();
outStream = s.getOutputStream();
inStreamScanner = new Scanner(inStream);
outStreamPrinter = new PrintWriter(outStream);
serverInstance.run();
}
public void run() {
try {
try {
doService();
} finally {
s.close();
}
} catch (IOException e) {
System.err.println(e);
}
}
public void doService() throws IOException{
while(true) {
if(inStreamScanner.hasNext())
return;
else {
outStreamPrinter.println("NO REQUEST");
outStreamPrinter.flush();
String request = inStreamScanner.next();
outStreamPrinter.println("Request received: " +request);
outStreamPrinter.flush();
handleServerRequest(request);
}
}
}
public void handleServerRequest(String request) throws IOException{
if(request.startsWith("SUBMIT")) {
String token = extractNum(request);
addtoTS(token);
} else if(request.startsWith("REMOVE")) {
String token = extractNum(request);
removefromTS(token);
} else if(request.startsWith("QUIT")) {
s.close();
} else {
outStreamPrinter.println("UNKNOWN REQUEST");
outStreamPrinter.flush();
}
}
public String extractNum(String request) {
String str = request;
String numberOnly = str.replaceAll("[^0-9]", " ");
return numberOnly;
}
public void addtoTS(String token) {
if(ts.contains(token)) {
outStreamPrinter.println("OK");
outStreamPrinter.flush();
}else {
ts.add(token);
outStreamPrinter.println("OK");
outStreamPrinter.flush();
}
}
public void removefromTS(String token) {
if(ts.contains(token)) {
ts.remove(token);
outStreamPrinter.println("OK");
outStreamPrinter.flush();
}else {
outStreamPrinter.println("ERROR: TOKEN NOT FOUND");
outStreamPrinter.flush();
}
}
}
I haven't run the code, but there seems to be an issue in your doService() method on the server side. You have an infinite loop, but the entire method returns (and thus the program also quits) as soon as the input stream recieves a new line character (when the client sends a request). So, it seems your program would quit when it receives the first command from the client. I'd also recommend closing more gently (ie check in the loop for end rather than closing the socket directly).
So, I'd define a private class variable boolean listening; or something like that. Then in the main() method, set it to true after the socket has been initialized (when the client has connected).
Change your doService() to something similar to the following:
public void doService() throws IOException
{
while(listening)
{
if(inputStreamReader.hasNext())
{
String request = inStreamScanner.next();
outStreamPrinter.println("Request received: " +request);
outStreamPrinter.flush();
handleServerRequest(request);
}
}
}
And change how you handle the QUIT command:
from
else if(request.startsWith("QUIT"))
{
s.close();
}
to
else if(request.startsWith("QUIT"))
{
listening = false;
}
The socket will be closed by the finally in run().
Below is my code for a simple Concurrent Server. Whenever I run multiple clients, the server only prints out the input of the first client. I'm not sure what I've done wrong. Any help would be appreciated.
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8001);
while (true){
Socket clientSocket = serverSocket.accept();
System.out.println(clientSocket);
ConcurrentServer client = new ConcurrentServer(clientSocket);
client.start();
}
} catch (IOException i){}
}
public void run(){
try {
inputStream = new BufferedReader(new InputStreamReader(concurrentSocket.getInputStream()));
outputStream = new PrintWriter(new OutputStreamWriter(concurrentSocket.getOutputStream()));
String testString = inputStream.readLine();
System.out.println(testString);
} catch (IOException i){}
}
This code might help you to understand how to run multiple clients concurrently. :)
What this code does? TCP Client sends a string to the server and TCP server sends back the string in UPPERCASE format & the server can do this concurrently with multiple connections.
I have included 3 files for the server and one more for testing the server with multiple clients(ClientTest.java)
Main.java
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
new Server(3000).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server.java
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Logger;
public class Server {
private ServerSocket sSocket;
private boolean run;
private int port;
public Server(int port) throws IOException {
this.port = port;
this.sSocket = new ServerSocket(this.port);
}
public void start() {
this.run = true;
Logger.getLogger(getClass().getName()).info("Server is listening on port: " + port);
try {
while (run) {
Socket cs = sSocket.accept();
Logger.getLogger(getClass().getName())
.info("New Client Connected! " + cs.getPort());
new Thread(new Client(cs)).start(); // Put to a new thread.
}
} catch (IOException e) {
Logger.getLogger(getClass().getName()).severe(e.getMessage());
}
}
public void stop() {
this.run = false;
}
}
Client.java (Client Process on server)
import java.io.*;
import java.net.Socket;
import java.util.logging.Logger;
public class Client implements Runnable {
private Socket clientSocket;
private DataOutputStream out; // write for the client
private BufferedReader in; // read from the client
public Client(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
// Do client process
outToClient(inFromClient().toUpperCase());
closeConnection();
}
private String inFromClient() {
String messageFromClient = "";
/*
* Do not use try with resources because once -
* - it exits the block it will close your client socket too.
*/
try {
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
messageFromClient = in.readLine();
} catch (IOException e) {
Logger.getLogger(getClass().getName()).severe("InFromClientErr - " + e.getMessage());
}
return messageFromClient.trim().equals("") ? "No Inputs given!" : messageFromClient;
}
private void outToClient(String message) {
try {
out = new DataOutputStream(clientSocket.getOutputStream());
out.writeBytes(message);
} catch (IOException e) {
Logger.getLogger(getClass().getName()).severe("OutToClientErr - " + e.getMessage());
}
}
private void closeConnection() {
try {
in.close();
out.close();
clientSocket.close();
} catch (NullPointerException | IOException e) {
Logger.getLogger(getClass().getName()).severe(e.getMessage());
}
}
}
ClientTest.java (For Testing clients)
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class ClientTest {
public static void main(String[] args) {
Socket clientSocket;
try {
clientSocket = new Socket("localhost", 3000);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(new Scanner(System.in).nextLine() + '\n'); // Get user input and send.
System.out.println(inFromServer.readLine()); // Print the server response.
} catch (IOException e) {
e.printStackTrace();
}
}
}
The issue was instead with the client. Not the server. The socket was declared outside of the for loop, and therefore only one connection was being created. Like so below:
public static void main(String[] args) {
try {
socket = new Socket("127.0.0.1", 8001);
for (int i = 0; i < 5; i++){
System.out.println("Starting client: " + i);
ConcurrentClient concurrentClient = new ConcurrentClient(socket, i);
concurrentClient.run();
}
} catch (IOException io) {
}
}
The Socket should be declared inside the for loop like so:
public static void main(String[] args) {
try {
for (int i = 0; i < 5; i++){
socket = new Socket("127.0.0.1", 8001);
System.out.println("Starting client: " + i);
ConcurrentClient concurrentClient = new ConcurrentClient(socket, i);
concurrentClient.run();
}
} catch (IOException io) {
}
}
I really don't know why you need so complex structure of input and output streams. It is better to use Scanner that will wait for the new input.
Also you can use PrintWriter to output the results of your conversation.
Here is server that accepts multiple clients:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ConcurrentServer extends Thread {
private Socket concurrentSocket;
public ConcurrentServer(Socket clientSocket) {
this.concurrentSocket = clientSocket;
}
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8001);
while (true){
Socket clientSocket = serverSocket.accept();
System.out.println(clientSocket);
ConcurrentServer client = new ConcurrentServer(clientSocket);
client.start();
}
} catch (IOException i){}
}
public void run(){
try {
InputStream inputStream = concurrentSocket.getInputStream();
Scanner scanner = new Scanner(inputStream);
OutputStream outputStream = concurrentSocket.getOutputStream();
PrintWriter pw = new PrintWriter(outputStream);
while(scanner.hasNextLine()){
String line = scanner.nextLine();
System.out.println(line);
pw.println("message: " + line);
pw.flush();
}
} catch (IOException i){}
}
}
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 learn how to use java sockets before next semester. I wrote this program that is supposed to accept accept a message from a sender and send the message to a reciever. You specify the reciever by writing the name of the client that is connected, if the client isn't connected then the server will respond by sending the message "DISCONNECTED". But for some reason the message isn't sent to the reciever. I can still send the message to the sender though. Is this the right forum to ask for this kind of help?
This is my client class
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class MyTestClient {
static int port = 0;
static String ip = "";
static String name = "";
public static void main(String args[] ) {
if(args.length == 3) {
try{
port = Integer.parseInt(args[1]);
} catch(NumberFormatException e) {
System.out.println("Usage: Java MyTestClient <ip> <port> <name>");
System.exit(0);
}
ip = args[0];
name = args[2];
} else {
System.out.println("Usage: Java MyTestClient <ip> <port> <name>");
System.exit(0);
}
try {
Socket socket = new Socket(ip, port);
new Thread(new MessageHandler(socket)).start();
new Thread(new InputHandler(socket)).start();
} catch (IOException e) {
System.out.println("Could not connect to: " + ip + " : " + port);
System.exit(0);
}
}
public static class MessageHandler implements Runnable {
Socket socket;
public MessageHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
PrintWriter out = null;
BufferedReader in = null;
try {
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}catch(IOException e) {
e.printStackTrace();
}
String fromServer;
try {
while ((fromServer = in.readLine()) != null) {
System.out.println(fromServer);
fromServer.trim();
if(fromServer.contains(" ")) {
String split[] = fromServer.split(" ", 2);
System.out.println(split.length == 2 ? split[1] + " Is a two part message" : "Strange message");
} else {
if(fromServer.equals("NAME")) {
System.out.println("Server asks for name | gives given name to server");
out.println(name);
}
if(fromServer.equals("SUCCESS")) {
System.out.println("Message succesfully sent");
}
if(fromServer.equals("ERROR")) {
System.out.println("Something went wrong when sending the message");
}
if(fromServer.equals("OCCUPIED")) {
System.out.println("Name was already used. Start the program with another name");
socket.close();
System.exit(0);
}
if(fromServer.equals("DISCONNECTED")) {
System.out.println("The reciever was not connected");
}
if(fromServer.equals("REGISTERED")) {
System.out.println("Successfully logged in to server");
}
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
}
public static class InputHandler implements Runnable {
Socket socket;
public InputHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
String fromUser = null;
PrintWriter out = null;
try {
out = new PrintWriter(socket.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader kbi = new BufferedReader(new InputStreamReader(System.in));
try {
while ((fromUser = kbi.readLine()) != null) {
out.println(fromUser);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
This is my server class
import java.io.*;
import java.net.*;
import java.util.*;
public class MyServer {
public static int port;
public static int maxConnections;
public static final String NAME = "Server";
private static Map<String, Socket> socketsMap = new HashMap<>();
public static void main(String args[]) {
if(args.length == 2) {
try{
port = Integer.parseInt(args[0]);
maxConnections = Integer.parseInt(args[1]);
}catch(Exception e){
System.out.println("Usage: Java Myserver <port> <maxConnections>");
System.exit(0);
}
} else {
System.out.println("Usage: Java Myserver <port> <maxConnections>");
System.exit(0);
}
new Thread(new ConnectionHandler(port, maxConnections)).start();
}
public static class ConnectionHandler implements Runnable {
private ServerSocket server;
private Socket socket = null;
public int currentSocket = 0;
public int port = 0;
public int maxConnections = 0;
public ConnectionHandler(int port, int maxConnections) {
this.maxConnections = maxConnections;
this.port = port;
}
#Override
public void run() {
try {
server = new ServerSocket(7777);
} catch (IOException e1) {
System.out.println("Server could not connect to port: " + port);
e1.printStackTrace();
System.exit(0);
}
while(currentSocket++ < maxConnections) {
try {
socket = server.accept();
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println("NAME");
String message;
while((message = in.readLine()) != null) {
if(!socketsMap.containsKey(message) || message.equals("SERVER")) {
out.println("REGISTERED");
socketsMap.put(message, socket);
System.out.println(message + " has logged on server");
new Thread(new SocketHandler(socketsMap.get(message))).start();
} else {
out.println("OCCUPIED");
System.out.println(socket.getInetAddress().toString() + " has tried to login with existing name " + message);
socket.close();
currentSocket--;
}
socket = null;
break;
}
} catch (IOException e) {
System.out.println("Something went wrong with client connection");
}
}
}
}
public static class SocketHandler implements Runnable {
Socket socket = null;
public SocketHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter respond = new PrintWriter(socket.getOutputStream(), true);
String input;
while((input = in.readLine() ) != null) {
String[] info = input.split(" ", 2);
if(info.length != 2){
System.out.println("Message computed wrong");
respond.println("ERROR");
break;
}
if(info[0].equals("SERVER")) {
//TODO: Write a server command handler class
} else if ( socketsMap.containsKey(info[0]) ){
Socket reciever = socketsMap.get(info[0]);
PrintWriter out = new PrintWriter(reciever.getOutputStream());
respond.println("SUCCESS");
System.out.println(info[0] + " send the message: "+ info[1]);
out.println("MESSAGE" + " " + info[1]);
break;
} else {
System.out.println("Reciever is not connected");
respond.println("DISCONNECTED");
}
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
Maybe you can run it on your computers and see what i mean?
#Override
public void run() {
try {
server = new ServerSocket(7777);
} catch (IOException e1) {
System.out.println("Server could not connect to port: " + port);
e1.printStackTrace();
System.exit(0);
}
change the code above to
#Override
public void run() {
try {
server = new ServerSocket(port);
} catch (IOException e1) {
System.out.println("Server could not connect to port: " + port);
e1.printStackTrace();
System.exit(0);
}
I want that message sent by server should be delivered to all the clients however a message sent by by client should only be delivered to server.
Problem is when i run the code-
1.Server waits for client to connect
2.when multiple client connected
3.Now as the server broadcast the first message it is received by both the clients but when server broadcast the message second time. Both the clients has to send message in order to receive server message.
I am a noob in socket programming so please correct me what i am doing wrong?
So far i have made this program.
Server Code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;
import java.net.*;
import java.io.*;
public class Server_Side3
{
static Client_server t[] = new Client_server[10];
static LinkedList<Client_server> al = new LinkedList<Client_server>();
public static void main(String args[]) throws IOException
{
ServerSocket server = null ;
Socket socket = null;
try
{
int Port =9777;
server = new ServerSocket(Port);
System.out.println("Waiting for Client " + server);
while(true)
{
socket = server.accept();
System.out.println("Connected to " + socket.getLocalAddress().getHostAddress());
Client_server clients = new Client_server(socket);
al.add(clients);
clients.start();
}
}
catch (Exception e)
{
System.out.println("An error occured.");
e.printStackTrace();
}
try
{
server.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private static class Client_server extends Thread
{
Socket sockets;
PrintWriter out;
Client_server t[];
Client_server (Socket s )
{
sockets = s;
}
public void run()
{
try
{
InetAddress localaddr = InetAddress.getLocalHost();
Scanner sc = new Scanner(System.in);
Scanner in = new Scanner(sockets.getInputStream());
out = new PrintWriter(sockets.getOutputStream(),true);
String input = null;
while(true)
{
String servermsg = sc.nextLine();
broadcast(servermsg);
System.out.println("Message sent to client: "+servermsg);
input = in.nextLine();
System.out.println(localaddr.getHostName()+" Said :"+ input);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void broadcast(String servermsg)
{
Iterator it = al.iterator();
while(it.hasNext())
{
((Client_server) it.next()).send(servermsg);
}
}
private void send(String msg)
{
String servrmsg = msg;
out.println(msg);
out.flush();
}
}
}
Client Code :
import java.net.Socket;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientSide2
{
static Scanner chat = new Scanner(System.in);
public static void main(String[] args)
{
int Port = 9777;
String Host = "localhost";
try
{
Socket socket = new Socket(Host, Port);
System.out.println("You connected to "+ Host);
Scanner in = new Scanner(socket.getInputStream()); //GET THE CLIENTS INPUT STREAM
PrintWriter out = new PrintWriter(socket.getOutputStream());
String clientinput;
while(true)
{
System.out.println(in.nextLine());//If server has sent us something .Print it
clientinput=chat.nextLine();
out.println(clientinput); //SEND IT TO THE SERVER
out.flush();
}
}
catch (Exception e)
{
System.out.println("The server might not be up at this time.");
System.out.println("Please try again later.");
}
}
}