send message to specific clients using java - java

How can i send message from server to any specific client. I have the concept of how to do it like i have to make a list of all the clients connected to server and then by iterating each client i can send message but i will be thankful if any one can help me by code.I have searched many codes but i didn't get any considerable help from them Code shouldn't be GUI based. Thanks in advance.Sorry for my bad English.
This is my code in which message is send to all clients but i want to send message to a client of my choice using clients ipaddress
Map<Integer, java.net.Socket> clients = new HashMap<Integer, java.net.Socket> ();
socket = serverSocket.accept();
// Add the socket to a HashMap
clients.put(socket.getPort(), socket);
for (Iterator<Integer> iter = clients.keySet().iterator(); iter.hasNext(); )
{
int key = iter.next();
java.net.Socket client = clients.get(key);
// Sending the response back to the client.
// Note: Ideally you want all these in a try/catch/finally block
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("Some message");
bw.flush();
}

What I would do is create a Client class:
class Client
{
private String userName;
private String ipAddress;
private java.net.Socket socket = null;
public Client (String userName, String ipAddress, java.net.Socket socket)
{
this.userName = userName;
this.ipAddress = ipAddress;
this.socket = socket;
}
public java.net.Socket getSocket()
{
return this.socket;
}
}
Instead of adding just the socket and port number to the map, I would map the combination of the userName and ipAddres to a Client object.
socket = serverSocket.accept();
// get the username from the socket
// get the ipAddress from the socket
Client c = new Client(userName, ipAddress, socket);
// Add the client to a HashMap
clients.put(userName + ":" + ipAddress, c);
Now, you can send a message to a specific client based on the username and ipAddress:
public void sendToOneClient (String userName, String ipAddress, Map<String, Client> clients)
{
Client c = clients.get(userName + ":" + ipAddress);
java.net.Socket socket = c.getSocket();
// Sending the response back to the client.
// Note: Ideally you want all these in a try/catch/finally block
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("Some message");
bw.flush();
}

I'd use Socket.getInetAddress() and compare the result to whatever you have the IPs you want to send to in. Personally, I'd use a String[] or ArrayList<String> for that. Here's an example:
ArrayList<String> addresses;
//TODO: Add things to 'addresses'
clients.put(socket.getPort(), socket);
for (Iterator<Integer> iter = clients.keySet().iterator(); iter.hasNext(); )
{
int key = iter.next();
java.net.Socket client = clients.get(key);
//Checking to make sure it's a client we want to send to.
if (addresses.contains(client.getInetAddress().toString()) {
// Sending the response back to the client.
// Note: Ideally you want all these in a try/catch/finally block
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("Some message");
bw.flush();
}
}
Alternatively, you could store the sockets in your HashMap by the InetAddress instead.

You can store a relationship between how you want to look up the client with the socket that they are on. The natural way to do this is with a map, like
Map<String, Socket> sockets = new HashMap<String,Socket>();
...
ServerSocket ss = ...;
Socket s = ss.accept();
String username = getUserName(s);
sockets.put(username, s);
Obviously, in this example here, the client would have to send his/her userName in a format which you expect to receive after making the Socket connection

I have found that it is effective to create an object type that can hold both a unique name or id be it an int or a String and also a Socket. You could store instances of this object in an ArrayList (or any other list) and iterate through them searching for the name or id that you want to use.

This is what I did for my program.Here I used the ">>" string to specify that a message should be sent to a particular user. (e.g.: "Ross>>Hi Ross What's Up?" means that the message should be sent to the user named 'Ross'). I used a HashMap(named 'WritersMap') to keep details as KEY-VALUE pairs. Key will be the name of the user who sends the particular message and Value will be that message. 'in' is a BufferedReader instance.
while (true) {
String input = in.readLine();
if (input == null) //if there is no input,do nothing
{
return;
}
//when a user sends a message to a specific user
else if(input.contains(">>")) //checks whether the message contains a >>
{
String person=input.substring(0,input.indexOf(">")); //extract the name of the destination user
for(HashMap.Entry<String,PrintWriter> entry:writersMap.entrySet()) //find the destination user from the users list
{
if(entry.getKey().matches(person)) //if the destination user is found
{
PrintWriter writer=entry.getValue();
writer.println("MESSAGE " + name + ": " + input);
}
}
}
else //when a user sends a broadcast message to all users
{
for(HashMap.Entry<String,PrintWriter> entry:writersMap.entrySet()) //find the destination user from the users list
{
PrintWriter writer=entry.getValue();
writer.println("MESSAGE " + name + ": " + input);
}
}
}

Related

send objects from server to client in java sockets

I want to send objects from the server to the client in java sockets. I can send them from client to the server, however I am struggling to send them from server to client. I am new to Java so I'm still learning the basics. I know its something relatively minor that I need to do, however i am struggling with it at the moment. Can someone add the bits of code that i am missing?
Open another connection in another thread and let the client be server, and server be client. So in one thread you send A -> B, in another thread you open another socket and begin to send b B -> A.
The problem with low level sockets is that if one side is writing, the other should be listening. That means you have to implement command-query protocol, which is a heavy task. So with my proposal you will use two ports but you know that you will have 2 pipes of data flow.
A --8888--> B
A <--8889-- B
It will be easier if you are just starting with sockets.
You can use ObjectOutputStream to send an object through the socket and ObjectInputStream to receive one:
private ObjectOutputStream oos;
private ObjectInputStream ois;
public SocketHandler(Socket cs) {
this.oos = new ObjectOutputStream(cs.getOutputStream());
this.ois = new ObjectInputStream(cs.getInputStream());
}
public void sendObject(Object o) {
this.oos.writeObject(o);
this.oos.flush();
}
public Object receiveObject() {
return this.ois.readObject();
}
That was assuming you want to send and receive an Object. You can also use PrintWriter and BufferedReader to send and receive String messages and after parsing it:
private PrintWriter pw;
private BufferedReader br;
public SocketHandler(Socket cs) {
this.pw = new PrintWriter(cs.getOutputStream());
this.br = new BufferedReader(new InputStreamReader(cs.getInputStream()));
}
public void sendMsg(String msg) {
this.pw.println(msg);
this.pw.flush();
}
public String receiveMsg() {
return this.br.readLine();
}
Below I have an example of some Server-Side code that I used for an application a while ago, then I will give you an explanation as to what's going on here:
first you need to create your ServerSocket in order to accept client requests (as you already know):
ServerSocket serverSocket = new ServerSocket(1002);
while(true) {
Then you need to enter a while loop in order to receive requests for as long as the Server program is alive
Socket clientSocket = serverSocket.accept();
System.out.println("Connection made to: " + clientSocket);
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String messageString = "";
String line;
System.out.println("Enter while loop to retrieve client message...");
while((line = br.readLine()) != null) {
String clientRequestLine = line;
if(clientRequestLine.contains("check return user credentials")) {
String userNamePassWord = clientRequestLine.replace("check return user credentials", "");
userNamePassWord = userNamePassWord.trim();
String[] userNamePassWordSplitter = userNamePassWord.split(" ");
String userName = userNamePassWordSplitter[0];
String passWord = userNamePassWordSplitter[1];
System.out.println("Username: " + userName + "\nPassword: " + passWord);
boolean isValidUserNamePassWord = ReturnPatientCredentials.checkUserNamePassWord(userName, passWord);
if(isValidUserNamePassWord) {
System.out.println("valid");
out.println("valid");
}
else {
System.out.println("invalid");
out.println("invalid");
}
}
Above you need to start a BufferedReader in order to store an InputStream (the data) from the client socket. You also need to create a PrintWriter so that you can send data to the OutputStream and you need to pass your clientSocket as the argument for the OutputStream. Next you'll create variables to get the message and the "line" of date from the client and enter a while loop. You can then store the line in a variable and read the data or whatever you need to do. We use our PrintWriter (out) to send data back with the println() method and then we can break out of the loop when needed.

Simple Java Networking Program

I'm new to Java programming and I'm just trying to get a very basic networking program to work.
I have 2 classes, a client and a server. The idea is the client simply sends a message to the server, then the server converts the message to capitals and sends it back to the client.
I'm having no issues getting the server to send a message to the client, the problem is I can't seem to store the message the client is sending in a variable server side in order to convert it and so can't send that specific message back.
Here's my code so far:
SERVER SIDE
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket (9091);
while (true) {
System.out.println("Waiting");
//establish connection
Socket client = server.accept();
System.out.println("Connected " + client.getInetAddress());
//create IO streams
DataInputStream inFromClient = new DataInputStream(client.getInputStream());
DataOutputStream outToClient = new DataOutputStream(client.getOutputStream());
System.out.println(inFromClient.readUTF());
String word = inFromClient.readUTF();
outToClient.writeUTF(word.toUpperCase());
client.close();
}
}
}
CLIENT SIDE
public class Client {
public static void main(String[] args) throws IOException {
Socket server = new Socket("localhost", 9091);
System.out.println("Connected to " + server.getInetAddress());
//create io streams
DataInputStream inFromServer = new DataInputStream(server.getInputStream());
DataOutputStream outToServer = new DataOutputStream(server.getOutputStream());
//send to server
outToServer.writeUTF("Message");
//read from server
String data = inFromServer.readUTF();
System.out.println("Server said \n\n" + data);
server.close();
}
}
I think the problem might be with the 'String word = inFromClient.readUTF();' line? Please can someone advise? Thanks.
You're discarding the first packet received from the client:
System.out.println(inFromClient.readUTF()); // This String is discarded
String word = inFromClient.readUTF();
Why not swap these?
String word = inFromClient.readUTF(); // save the first packet received
System.out.println(word); // and also print it

Java Message sent from client to server

I'm using a socket to connect my client with the server, I need a way so that when somebody tries to login on the client with an account, it sends the username and password to the server, and checks if the account exists. I just need to know how to make it send the message to the server when they press login.
i tried this to make it send a message to the server
public static void sendmsg(String a, String b)
{
try
{
String host = "127.0.0.1";
int port = 43655;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String sendMessage = a;
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+sendMessage);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " +message);
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
//Closing the socket
try
{
socket.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
nice you are working with Sockets, well I have an approach you can try, and maybe if it is useful you can consider for your implementation.
First of all I will create an entity to handle those values and fill it with the incoming data.
class UserAuth {
private String username;
private String password;
//Consider here your getters and setters, I am not including them
}
I will use the entity as the parameter for the method while sending and maybe you can fill it as something like:
UserAuth attemptingUser = new UserAuth(...)
ObjectInputStream works fine for these kind of scenarios. If you still want to work with Strings, you can use BufferedReader and try to merge your username and password as one single String and use the .readLine() method to obtain (separated with commas), then use String methods such Split but I find that could take some more time, should be better if you handle it with an object. But it depends on the complexity you want to add to your application :).
class AuthClient {
public void sendMsg(UserAuth attemptingUser) {
String host = "localhost";
int port = 2055;
//1. Create the socket
Socket sender = new Socket(host, port);
//2. Create an object output stream to write the object into the stream
ObjectOutputStream outputWriter = new ObjectOutputStream(sender.getOutputStream());
//3. Write (send the object)
outputWriter.writeObject(attemptingUser);
//4. Close
outputWriter.close();
sender.close();
}
}
class AuthServer {
ServerSocket ss = new ServerSocket(2055);
public void receiveMsg() {
//1. Accept the connection
Socket conn = ss.accept();
//2. Receive the flow
ObjectInputStream readStream = new ObjectInputStream(conn.getInputStream());
//3. Read the object
UserAuth userReceived = readStream.readObject();
//4. Verify against file, db or whatever
if (userReceived.getUsername().equals("admin") && userReceived.getPassword().equals("admin")) {
//Authentication
}
}
}
(This is added as the part I edit for what you asked me in the comments)
public void sendMsg(String username, String password) {
String host = "localhost";
int port = 2055;
//1. Create the socket
Socket sender = new Socket(host, port);
//2. Create the UserAuth object based on the parameters you received
UserAuth myuser = new UserAuth();
myuser.setUsername(username);
myuser.setPassword(password);
//3. Follow same instructions for the creation of ObjectOutputStream...
ObjectOutputStream objectWriter = new ObjectOutputStream(sender.getOutputStream());
objectWriter.writeObject(myuser);
//That is what I would use if I keep your structure
}
If you want to keep your structure using Strings, I would simplify and reduce impact of I/O by using the String methods. Since you know you are always expecting user/password, I would merge your two params in one single String or use special char and on server side handle with StringTokenizer class. Or maybe handle with the "split" method. You have many options here.
So far, this will be my approach for the problem you are facing. Hope it helps somehow. Best regards and happy coding :).
What you have done looks OK to me but it all depends on what the server is expecting to receive. What is the terminating character as you have not sent one unless it's already contained within your String a variable.
If the server is expecting an end of line character (which you don't currently send) you can use a PrintWriter instead of a BufferedWriter like this
pw = new PrintWriter(socket.getOutputStream(), true);
pw.println(a);
Your server would then be doing something like this
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String value = br.readLine();

Connecting to socket to get data from it

I'm trying to connect to a web socket (Details: here ) to get information back from it.
As you can see I need clients IP address and so on, here's what I have so far:
//client IP address
//is client behind something?
String ipAddress = request.getHeader("X-FORWARDED-FOR");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
String socketAddress = "whois.nic.uk";
int socketPort = 1043;
Socket socket = new Socket(socketAddress, socketPort);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
//for every domain loop
String singleDomain = "google.co.uk"; //just an example
//<hostname of client> <IP address of client> <domain to query><cr><lf>
String whoIs2 = ipAddress + " " + ipAddress + " " + singleDomain + "\r\n";
//convert message to bytes
byte[] whoIs2B = whoIs2.getBytes();
Basically I'm not sure how to sent the whoIs2B (byte version to the socket if that makes sense?). I then need to change the byte response to text, that's all I need.
Note: Don't mind try / catches since I had to delete some unnecessary info to make it easier to see what I'm asking.
To send the bytes down the socket you need to write to the underlying stream 'out'.
You'd do something similar for the input stream.
http://docs.oracle.com/javase/tutorial/networking/sockets

Debugging a socket communication program

I have 2 classes (Client and Server) used to implement simple communication in my application. My code is shown below:
Server:
public class Server {
public static void main(String[] ar) {
int port = 1025; // just a random port. make sure you enter something between 1025 and 65535.
try {
ServerSocket ss = new ServerSocket(port); // create a server socket and bind it to the above port number.
System.out.println("Waiting for a client...");
Socket socket = ss.accept();
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);
BufferedReader keyboard = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("enter meter id ");
String line = null;
while (true) {
line = in.readUTF(); // wait for the client to send a line of text.
System.out.println("client send me this id number " + line);
line = keyboard.readLine();
out.writeUTF(line);
out.flush();
//line = in.readUTF();
System.out.println("Waiting for the next line...");
System.out.println();
}
} catch (Exception x) {
x.printStackTrace();
}
}
}
Client:
public class Client {
public static void main(String[] ar) {
int serverPort = 1025;
String address = "localhost";
try {
InetAddress ipAddress = InetAddress.getByName(address); // create an object that represents the above IP address.
System.out.println(" IP address " + address + " and port "
+ serverPort);
Socket socket = new Socket(ipAddress, serverPort); // create a socket with the server's IP address and server's port.
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);
// Create a stream to read from the keyboard.
BufferedReader keyboard = new BufferedReader(new InputStreamReader(
System.in));
String line = null;
System.out.println("ClientConnected.");
System.out.println("enter meter id");
while (true) {
line = keyboard.readLine(); // wait for the user to type in something and press enter.
System.out.println("Sending this number to the server...");
out.writeUTF(line); // send the above line to the server.
out.flush(); // flush the stream to ensure that the data reaches the other end.
line = in.readUTF(); // wait for the server to send a line of text.
System.out
.println("The server was very polite. It sent me this : "
+ line);
System.out.println();
}
}
catch (Exception x) {
x.printStackTrace();
}
}
}
My problem is that while testing the program I do get communication between the client and server, but while debugging, with a break point on the out.flush line in Server.java, it does not go to the intended destination. This intended destination being the line line = in.readUTF(); of Client.java. Can anyone help me to solve this?
It is good practice to open the OutputStreams before the InputStreams, on your sockets, as said in this question.
This question also clarifies that.
What I suspect here is your client and server are running in two different JVM processes and java debugger cannot debug two JVM at the same time.

Categories