I've searched for examples of how to implement a simple ipv6 multicast example, however I have only found examples using ipv4.
Can anybody provide a simple "helloworld" example of ipv6 multicasting?
Here is a simple client server example. Incidentally running it on multiple machines on a network wil get all the machines chatting to each other, good for testing automatic discovery on the network.
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UdpBroadcaster {
private static final Logger LOGGER = LoggerFactory.getLogger(UdpBroadcaster.class);
private static final int PORT = 9876;
private static final String MCAST_ADDR = "FF7E:230::1234";
private static InetAddress GROUP;
public static void main(String[] args) {
try {
GROUP = InetAddress.getByName(MCAST_ADDR);
Thread server = server();
server.start();
Thread.sleep(3000);
Thread client = client();
client.start();
client.join();
} catch (Exception e) {
LOGGER.error("Usage : [group-ip] [port]");
}
}
private static Thread client() {
return new Thread(new Runnable() {
public void run() {
MulticastSocket multicastSocket = null;
try {
multicastSocket = new MulticastSocket(PORT);
multicastSocket.joinGroup(GROUP);
while (true) {
try {
byte[] receiveData = new byte[256];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
multicastSocket.receive(receivePacket);
LOGGER.info("Client received from : " + receivePacket.getAddress() + ", " + new String(receivePacket.getData()));
} catch (Exception e) {
LOGGER.error(null, e);
}
}
} catch (Exception e) {
LOGGER.error(null, e);
} finally {
multicastSocket.close();
}
}
});
}
private static Thread server() {
return new Thread(new Runnable() {
public void run() {
DatagramSocket serverSocket = null;
try {
serverSocket = new DatagramSocket();
try {
while (true) {
byte[] sendData = new byte[256];
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, GROUP, PORT);
serverSocket.send(sendPacket);
ThreadUtilities.sleep(1000);
}
} catch (Exception e) {
LOGGER.error(null, e);
}
} catch (Exception e) {
LOGGER.error(null, e);
}
}
});
}
}
Hope that helps.
M
The only difference between an IPv6 program and an IPv4 program in Java is the IP addresses. In this case you have to use an IPv6-style multicast address when joining the group, and when sending to it. Everything else is the same.
Related
I made a client-server program that works well on the same machine but I cannot get it to run on different laptops.
I checked the ports and the multicast address and everything matches.
This is my client:
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class BroadcastClient {
public InetAddress address;
public byte[] buffer;
public DatagramPacket packet;
public String str, str2;
public MulticastSocket socket;
public BroadcastClient() throws Exception{
socket = new MulticastSocket(1502);
System.out.println("Waiting for messages from server");
transmit();
}
public void transmit(){
try{
//receive data using port
address = InetAddress.getByName("233.0.0.1");
//register client to the group multicast
socket.joinGroup(address);
while (true){
buffer = new byte[256];
packet = new DatagramPacket(buffer, buffer.length);
//receive data from server
socket.receive(packet);
str = new String(packet.getData());
System.out.println("Received message: " + str);
}
}catch (Exception e){
System.out.println("error: " + e);
}finally {
try {
//remove client from multicast group
socket.leaveGroup(address);
//close socket
socket.close();
}catch (Exception e){
System.out.println("Error: "+ e);
}
}
}
}
And this is my server:
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
public class BroadcastServer {
BufferedReader in = null;
String str = null;
byte[] buffer;
DatagramPacket packet;
InetAddress address;
int port;
DatagramSocket socket;
public BroadcastServer() throws IOException {
System.out.println("Sending message");
//create to receive
socket = new DatagramSocket();
transmit();
}
public void transmit() {
try {
in = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.println("Send to everyone");
str = in.readLine();
buffer = str.getBytes();
address = InetAddress.getByName("233.0.0.1");
//send data to port 1502
packet = new DatagramPacket(buffer, buffer.length, address, 1502);
//send messages to all clients
socket.send(packet);
}
} catch (Exception e) {
System.out.println("Error 2: " + e);
} finally {
try {
in.close();
} catch (Exception e) {
System.out.println("Error3: " + e);
}
}
}
}
This is how I call them:
Client:
public class UDPClient {
public static void main(String[] args) throws Exception {
BroadcastClient client = new BroadcastClient();
}
}
Server:
public class UDPServer {
public static void main(String[] arg) throws Exception {
//start
BroadcastServer server = new BroadcastServer();
}
}
Am I missing something? I cannot figure it out at all. The router could be my problem?
I'm trying to do a simple group chat where there's a server and several clients.
The objective is when a client sends a message to the server, the server just sends that message back to all the other clients. I had the server send a message writen by him send to all the clients but he didn't send the clients message.
Server code:
package Group;
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.*;
public class GroupServer extends Thread {
private ServerSocket server;
protected List<ClientHandler> clients;
public static void main(String[] args) throws IOException {
new GroupServer(9876);
}
public GroupServer(int port) {
try {
this.server = new ServerSocket(port);
System.out.println("New server initialized!");
clients = Collections.synchronizedList(new ArrayList<ClientHandler>());
this.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
try {
Socket client = server.accept();
System.out.println(client.getInetAddress().getHostName() + " connected");
ClientHandler newClient = new ClientHandler(client);
clients.add(newClient);
new SendMessage(clients);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class ClientHandler {
protected Socket client;
protected PrintWriter out;
protected DataInputStream in;
public ClientHandler(Socket client) {
this.client = client;
try {
this.out = new PrintWriter(client.getOutputStream());
this.in = new DataInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SendMessage extends Thread {
protected List<ClientHandler> clients;
protected String userInput;
protected String sendMessage;
protected BufferedReader stdIn;
protected DataInputStream in;
public SendMessage(List<ClientHandler> clients) {
this.clients = clients;
this.userInput = null;
this.start();
}
public void run() {
System.out.println("New Communication Thread Started");
if (clients.size() == 1) {
System.out.println("Enter message:");
}
try {
if (clients.size() > 0) {
this.stdIn = new BufferedReader(new InputStreamReader(System.in));
while ((this.userInput = stdIn.readLine()) != null) {
if (userInput != null & userInput.length() > 0) {
for (ClientHandler client : clients) {
sendMessage = client.in.readUTF();
client.out.println(sendMessage);
client.out.flush();
Thread.currentThread();
Thread.sleep(1 * 1000);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The client code:
package Group;
import java.net.*;
import java.io.*;
import java.util.logging.*;
public class GroupClient {
protected Socket client;
protected BufferedReader in;
public static void main(String[] args) {
new GroupClient("Localhost", 9876);
}
public GroupClient(String hostName, int ip) {
try {
this.client = new Socket(hostName, ip);
this.in = new BufferedReader(new InputStreamReader(
this.client.getInputStream()));
String buffer = null;
while ((buffer = in.readLine()) != null) {
System.out.println(buffer);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I think the error is in the Server, more preciselly on the SendMessage class.
Thank you for the attention.
You have just one thread "SendMessage" for all the clients.
The very first time you call client.in.readUTF() in a loop, the thread blocks till that client has sent something. Since all the other clients are handled by the same thread. All of them are blocked too.
Either you have one thread per client socket or go the nio selector way (preferrable).
Also fix the issues mentioned by #jingx.
For synchronized arraylist, use CopyOnWriteArrayList. It is specifically meant for these kind of usecases. Synchronization help in concurrent addition and deletion but not during concurrent iteration. CopyOnWriteArrayList solves that problem.
I am having a simple Peer to Peer program written in java. I have the following code.
import java.net.*;
import java.io.*;
public class Broadcasts {
private final Runnable receiver;
private final Runnable sender;
private boolean run = true;
public Broadcasts(UDPSocketHandler parent) throws UnknownHostException{
InetAddress aHost = InetAddress.getLocalHost();
sender = new Runnable() {
public void run() {
byte data[] = "Hello".getBytes();
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
} catch (SocketException ex) {
ex.printStackTrace();
parent.quit();
}
DatagramPacket packet = new DatagramPacket(
data,
data.length,
aHost,
9090);
while (run) {
try {
System.out.println("what is sent"+new String(packet.getData()));
socket.send(packet);
Thread.sleep(1000);
} catch (IOException ex) {
ex.printStackTrace();
parent.quit();
} catch (InterruptedException ex) {
ex.printStackTrace();
parent.quit();
}
}
}
};
receiver = new Runnable() {
public void run() {
byte data[] = new byte[0];
DatagramSocket socket = null;
try {
socket = new DatagramSocket(9090);
} catch (SocketException ex) {
ex.printStackTrace();
//parent.quit();
}
DatagramPacket packet = new DatagramPacket(data, data.length);
//System.out.println("this is what has been received"+packet.getData());
String temp;
// while (run) {
try {
socket.receive(packet);
System.out.println("this is what has been received"+packet.getData());
//System.out.println("Message received ..."+ temp);
} catch (IOException ex) {
ex.printStackTrace();
parent.quit();
}
//}
}
};
new Thread(sender).start();
new Thread(receiver).start();
}
public void quit() {
run = false;
}
}
Then I have the following class to handle my communication
public class UDPSocketHandler {
private final Broadcasts broadcasts;
// continue running application?
private boolean run = true;
public UDPSocketHandler() throws UnknownHostException
{
// start socket server to accept incoming connections
new Thread().start();
// late initialize of UDP broadcast and receive, to ensure needed
// objects are instantiated
broadcasts = new Broadcasts(this);
}
// global quit method shuts down everything and exits
public void quit() {
run = false;
broadcasts.quit();
System.exit(0);
}
// application entry
public static void main(String[] args) throws UnknownHostException{
new UDPSocketHandler();
}
}
The problem is that the receiver do not receive anything. From what I understood, we could run the sender and receive on the same program as shown in this question. That is actually what I would like to do but using UDP instead of TCP. What is the problem with my code?
After some efforts and hours I have finally managed to to get my program working. I have the following:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.*;
public class SocketTest {
private boolean run = true;
public static void main(String[] args) throws IOException {
startServer();
startSender();
}
public static void startSender() throws UnknownHostException{
InetAddress aHost = InetAddress.getLocalHost();
(new Thread() {
#Override
public void run() {
byte data[] = "Hello".getBytes();
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
socket.setBroadcast(true);
} catch (SocketException ex) {
ex.printStackTrace();
//parent.quit();
}
DatagramPacket packet = new DatagramPacket(
data,
data.length,
aHost,
9090);
int i=0;
while (i<10) {
try {
System.out.println("what us mmmm.."+new String(packet.getData()));
socket.send(packet);
Thread.sleep(50);
i++;
System.out.println(i);
} catch (IOException ex) {
ex.printStackTrace();
// parent.quit();
} catch (InterruptedException ex) {
ex.printStackTrace();
// parent.quit();
}
}
}}).start();
}
public static void startServer() {
(new Thread() {
#Override
public void run() {
//byte data[] = new byte[0];
DatagramSocket socket = null;
try {
socket = new DatagramSocket(9090);
//socket.setBroadcast(true);;
} catch (SocketException ex) {
ex.printStackTrace();
//parent.quit();
}
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
//System.out.println("this is what has been received111"+packet.getData());
String temp;
while (true) {
try {
socket.receive(packet);
temp=new String(packet.getData());
System.out.println("this is what has been received"+temp);
//System.out.println("Message received ..."+ temp);
} catch (IOException ex) {
ex.printStackTrace();
//parent.quit();
}
}
}
}).start();
}
}
With this code, each node can act as both client and server. All we have to do is to pass the correct port number of a server to which we are sending the request. In this sample code, the port number is the same as the client sending the packet to itself. I hope this could help others
I am able to connect my DatagramSocket server and client inside my local area network(LAN) but I am unable outside of it.
Here is my code:
GameServer class:
public class GameServer extends Thread {
private DatagramSocket socket;
public GameServer() {
try {
this.socket = new DatagramSocket(7081,InetAddress.getByName("0.0.0.0"));
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
if(new String(packet.getData()).trim().equalsIgnoreCase("ping")){
sendData("pong".getBytes(),packet.getAddress(),packet.getPort());
}
System.out.println(new String(packet.getData()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendData(byte[] data, InetAddress ipAddress, int port) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port);
try {
this.socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
GameClient class:
public class GameClient extends Thread {
private InetAddress ipAddress;
private DatagramSocket socket;
public GameClient(String ipAddress) {
try {
this.socket = new DatagramSocket();
this.ipAddress = InetAddress.getByName(ipAddress);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
System.out.println(new String(packet.getData()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendData(byte[] data) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 7081);
try {
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
RunClient class:
public class RunClient {
public static void main(String[] args) {
GameClient client = new GameClient("/*Here is my external ip address*/"); //If i am running this for LAN then 192.168.1.67 and localhost work
client.start();
client.sendData("ping".getBytes());
}
}
RunServer class:
public class RunServer {
public static void main(String[] args) {
GameServer server = new GameServer();
server.start();
}
}
Here are my port forwarding configurations:
Some additional information:
My local ip address is 192.168.1.67
The port I am using is 7081
When I check my ip and port at http://www.canyouseeme.org it gave me the following error:
Error: I could not see your service on "my external ip" on port (7081)
I don't see any problem in your code. That site (http://www.canyouseeme.org) must be trying with TCP instead of UDP.
Please add exception for the port 7081 into firewall, so that it allow incoming connections on port.
when you are trying in LAN the IP might be different, when you are trying outside, you have to try with the external ip, which should be configured to redirect the request to your localip.
Thanks,
Ankireddy Polu
Try to do some concurrent messaging between the server and the client. When they first connect to eachother and the Server sends the test string, the client gets it perfectly fine the first time. And the client can SEND messages just fine to the Server. But my Client class cant constantly check for messages like my Server can and idk what's wrong. Any suggestions?
Server class code:
import java.lang.*;
import java.io.*;
import java.net.*;
import java.util.Random;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
String testMessage = "You are now connected and can begin chatting!";
boolean connected = false;
int port;
public Server(int port) {
this.port = port;
}
public void Open() {
//creates Threadpool for multiple instances of chatting
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
System.out.println("Opening...");
ServerSocket srvr = new ServerSocket(port);
while (true) {
Socket skt = srvr.accept();
clientProcessingPool.submit(new ClientTask(skt));
}
} catch (Exception e) {
try {
System.out.println(e);
System.out.print("You're opening too many servers in the same location, fool!\n");
ServerSocket srvr = new ServerSocket(port);
while (true) {
Socket skt = srvr.accept();
clientProcessingPool.submit(new ClientTask(skt));
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
private class ClientTask implements Runnable {
private final Socket skt;
private ClientTask(Socket skt) {
this.skt = skt;
}
#Override
public void run() {
//for sending messages
if (connected == false) {
System.out.println("======================");
System.out.println("Server has connected!");
processMessage(testMessage);
}
//for receiving messages
while (true) {
try {
// Read one line and output it
BufferedReader br = new BufferedReader(new InputStreamReader(skt.getInputStream()));
String incomingMessage = br.readLine();
if (incomingMessage != null) {
System.out.println("Server: Received message: " + incomingMessage);
processMessage(incomingMessage);
}
//br.close();
//skt.close(); //maybe delete
} catch (Exception e) {
System.out.println("Server had error receiving message.");
System.out.println("Error: " + e);
}
}
}
//for processing a message once it is received
public void processMessage(String message) {
PrintWriter out = null;
try {
out = new PrintWriter(skt.getOutputStream(), true);
} catch (IOException ex) {
System.out.println(ex);
System.out.println("Server had error sending message.");
}
System.out.print("Server: Sending message: " + message + "\n");
out.print(message);
out.flush();
connected = true;
try {
skt.shutdownOutput();
//out.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Client class code:
import java.lang.*;
import java.io.*;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
class Client {
public String message;
Socket skt;
public int port;
public Client(int port) {
this.port = port;
}
//for receiving messages from Server
public void receiveMessage() {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
skt = new Socket(InetAddress.getLocalHost().getHostName(), port);
while (true) {
clientProcessingPool.submit(new Client.ClientTask(skt));
}
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
//for sending messages to Server
public void sendMessage(String outgoingMessage) throws IOException {
try {
skt = new Socket(InetAddress.getLocalHost().getHostName(), port);
PrintWriter pw = new PrintWriter(skt.getOutputStream());
System.out.println("Client: Sending message: " + outgoingMessage);
pw.print(outgoingMessage);
pw.flush();
skt.shutdownOutput();
//skt.close(); //maybe delete
} catch (Exception e) {
System.out.println(e);
System.out.print("Client had error sending message.\n");
JOptionPane.showMessageDialog(null, "That User is not currently online.", "ERROR!!", JOptionPane.INFORMATION_MESSAGE);
}
}
private class ClientTask implements Runnable {
private final Socket skt;
private ClientTask(Socket skt) {
this.skt = skt;
}
#Override
public void run() {
while (true) {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
//while (!in.ready()) {}
String incomingMessage = in.readLine();
if (incomingMessage != null) {
System.out.println("Client: Received message: " + incomingMessage); // Read one line and output it
message = incomingMessage;
}
//skt.shutdownInput();
//in.close();
//skt.close(); //maybe delete
} catch (Exception e) {
System.out.print("Client had error receiving message.\n");
}
}
}
}
}
Streams cannot be re-wrapped. Once assigned to a wrapper, they must use that wrapper for the entire life-cycle of the stream. You also shouldn't close a stream until you are done using it, which in this case isn't until your client and server are done communicating.
In your current code, there are a few times where you re-initialize streams:
while (true) {
try {
//Each loop, this reader will attempt to re-wrap the input stream
BufferedReader br = new BufferedReader(new InputStreamReader(skt.getInputStream()));
String incomingMessage = br.readLine();
if (incomingMessage != null) {
System.out.println("Server: Received message: " + incomingMessage);
processMessage(incomingMessage);
}
//don't close your stream and socket so early!
br.close();
skt.close();
} catch (Exception e) {
//...
}
You get the idea; you can use this knowledge to find the stream problems in your client code as well.
With that said, servers are the middle-man between multiple clients. If you want to be able to type in the server's console to send a message to clients, it shouldn't go to only 1 client (unless you had a system that allowed you to specify a name). You need to store every connection in some kind of collection so when you type in the server's console, it goes to every client that's connected. This also helps when a client wants to send a message to every other client (global message). The server's main thread is primarily for accepting clients; I created another thread to allow you to type in the console.
As for your streams, you should create them whenever you start the ClientTask, both server side and client side:
public class Server {
private ExecutorService executor = Executors.newFixedThreadPool(10);
private Set<User> users = new HashSet<>();
private boolean running;
private int port;
public Server(int port) {
this.port = port;
}
public void start() {
running = true;
Runnable acceptor = () -> {
try(ServerSocket ss = new ServerSocket(port)) {
while(running) {
User client = new User(ss.accept());
users.add(client);
executor.execute(client);
}
} catch(IOException e) {
//if a server is already running on this port;
//if the port is not open;
e.printStackTrace();
}
};
Runnable userInputReader = () -> {
try(Scanner scanner = new Scanner(System.in)) {
while(running) {
String input = scanner.nextLine();
for(User user : users) {
user.send(input);
}
}
} catch(IOException e) {
//problem sending data;
e.printStackTrace();
}
};
Thread acceptorThread = new Thread(acceptor);
Thread userThread = new Thread(userInputReader);
acceptorThread.start();
userThread.start();
}
public void stop() {
running = false;
}
public static void main(String[] args) {
new Server(15180).start();
System.out.println("Server started!");
}
}
In the run() method is where the streams should be wrapped.
class User implements Runnable {
private Socket socket;
private boolean connected;
private DataOutputStream out; //so we can access from the #send(String) method
public User(Socket socket) {
this.socket = socket;
}
public void run() {
connected = true;
try(DataInputStream in = new DataInputStream(socket.getInputStream())) {
out = new DataOutputStream(socket.getOutputStream());
while(connected) {
String data = in.readUTF();
System.out.println("From client: "+data);
//send to all clients
}
} catch(IOException e) {
//if there's a problem initializing streams;
//if socket closes while attempting to read from it;
e.printStackTrace();
}
}
public void send(String message) throws IOException {
if(connected) {
out.writeUTF(message);
out.flush();
}
}
}
It's pretty much the same idea with the client:
1. Connect to Server
2. Create "communication" thread
3. Create "user input" thread (to receive input from console)
4. Start threads
public class Client {
private final String host;
private final int port;
private boolean connected;
private Socket socket;
public Client(String host, int port) {
this.host = host;
this.port = port;
}
public void start() throws IOException {
connected = true;
socket = new Socket(host, port);
Runnable serverInputReader = () -> {
try (DataInputStream in = new DataInputStream(socket.getInputStream())) {
while (connected) {
String data = in.readUTF();
System.out.println(data);
}
} catch (IOException e) {
// problem connecting to server; problem wrapping stream; problem receiving data from server;
e.printStackTrace();
}
};
Runnable userInputReader = () -> {
try (DataOutputStream out = new DataOutputStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in)) {
while (connected) {
String input = scanner.nextLine();
out.writeUTF(input);
}
} catch (IOException e) {
//problem wrapping stream; problem sending data;
e.printStackTrace();
}
};
Thread communicateThread = new Thread(serverInputReader);
Thread userThread = new Thread(userInputReader);
communicateThread.start();
userThread.start();
}
public static void main(String[] args) throws IOException {
new Client("localhost", 15180).start();
}
}
There are a few things I used in the code above that you may not be familiar with. They help simplify the syntax for your code:
Lambda Expressions - Prevents the need to create an anonymous class (or subclass) to declare a method
Try-With-Resources - Closes the resources specified automatically once the try block as ended
EDIT
When a user connects, you should store their connection by name or id. That way, you can send data to specific users. Even if your client is running on the same machine as the server, it's still the same idea: client connects to server, server sends message to client based on name or id:
while(running) {
User client = new User(ss.accept());
users.add(client); //add to set
executor.execute(client);
}
Right now, you are simply adding users to a Set. There is currently no way to grab a specific value from this set. What you need to do is give it some kind of "key". To give you an idea, here's an old algorithm I used to use. I have an array full of empty slots. When someone connects, I look for the first empty slot. Once an empty slot is found, I pass the user the index of the array it's being stored at (that will be the user's id), then store the user in the array at the specified index. When you need to send a message to someone, you can use the id to access that specific array index, grab the user you want and send a message:
class Server {
private int maxConnections = 10;
private ExecutorService executor = Executors.newFixedThreadPool(maxConnections);
private User[] users = new User[maxConnections];
//...
while(running) {
Socket socket = ss.accept();
for(int i = 0; i < users.length; i++) {
if(users[i] == null) {
users[i] = new User(socket, i);
executor.execute(users[i]);
break;
}
}
}
//...
public static void sendGlobalMessage(String message) throws IOException {
for(User user : users)
if(user != null)
user.send(message);
}
public static void sendPrivateMessage(String message, int id) {
User user = users[id];
if(user != null) {
user.send(message);
}
}
}
class User {
private Socket socket;
private int id;
private DataOutputStream out;
public User(Socket socket, int id) {
this.socket = socket;
this.id = id;
}
public void send(String message) throws IOException {
out.writeUTF(message);
out.flush();
}
public void run() {
DataInputStream in;
//wrap in and out streams
while(connected) {
String data = in.readUTF();
//Server.sendGlobalMessage(data);
//Server.sendPrivateMessage(data, ...);
sendMessage(data); //sends message back to client
}
}
}