Facilitate High availability cluster(HAC) in Java - java

For my class project I have the following problem. I am able to receive client information and re-send the info to the respective client. However, I am not being able to send every clients' info to every other client (Broadcast?). I also need to implement the given functions. Any help would be appreciated.
The goal is to design and implement a simple application layer protocol over UDP to
facilitate High Availability Cluster (HAC). HAC has a set of mechanism to detect failovers,
network/node failure etc. in order to re-route the traffic to the available systems. In this project
you will not be working on the questions like how to perform consistent failover, or high
availability distributed hypervisor. However, your task is to design and implement a protocol to
maintain the up-node information throughout the cluster.
Your designed protocol should perform the following functions:
a) To detect node failure periodically
b) To inform the other nodes in the network about the failure (peering option)
c) To be able to detect when the failed node comes back to life
d) To inform other nodes about the availability of new node
Client Class:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.*;
import java.util.Random;
public class UDPClient
{
DatagramSocket Socket;
public UDPClient()
{
}
public void createAndListenSocket() throws ClassNotFoundException, InterruptedException
{
try
{
Socket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] incomingData = new byte[1024];
String sentence = "Client 1 is up";
byte[] data = sentence.getBytes();
boolean flag = true;
CreatePacket packet = new CreatePacket(data, flag, data.length);
while(true)
{
//Serialize to send
Random rnd = new Random();
int timeout = rnd.nextInt(30);
Thread.sleep(timeout*1000);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(buffer);
out.writeObject(packet);
out.close();
buffer.close();
DatagramPacket sendPacket = new DatagramPacket(buffer.toByteArray(), buffer.size(), IPAddress, 9876);
Socket.send(sendPacket);
System.out.println("Message sent from client");
//Deserialize and receive packet from server
DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length);
Socket.receive(incomingPacket);
ByteArrayInputStream bis = new ByteArrayInputStream(incomingPacket.getData());
ObjectInputStream in = new ObjectInputStream(bis);
Object receivedPacket = in.readObject();
in.close();
InetAddress IPAddress1 = incomingPacket.getAddress();
int port = incomingPacket.getPort();
System.out.println();
System.out.println("Response from server: ");
System.out.println("Message : " + receivedPacket.toString());
System.out.println("Client IP: "+ IPAddress1.getHostAddress());
System.out.println("Client port: "+ port);
}
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (SocketException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception
{
UDPClient client = new UDPClient();
client.createAndListenSocket();
}
}
Server code:
public class UDPServer
{
DatagramSocket socket = null;
public UDPServer()
{
}
public void createAndListenSocket() throws ClassNotFoundException
{
try
{
socket = new DatagramSocket(9876);
byte[] incomingData = new byte[1024];
while (true)
{
DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length);
socket.receive(incomingPacket);
CreatePacket toSendPacket = new CreatePacket(incomingData, incomingData.length);
ArrayList <CreatePacket> clients = new ArrayList<CreatePacket>(4);
ByteArrayInputStream bis = new ByteArrayInputStream(incomingPacket.getData());
ObjectInputStream in = new ObjectInputStream(bis);
Object receivedPacket = in.readObject();
in.close();
clients.add(toSendPacket);
InetAddress IPAddress = incomingPacket.getAddress();
int port = incomingPacket.getPort();
System.out.println();
System.out.println("" + receivedPacket.toString());
System.out.println("Client IP: "+ IPAddress.getHostAddress());
System.out.println("Client port: "+ port);
DatagramPacket replyPacket = new DatagramPacket(incomingData, incomingData.length, IPAddress, port);
Thread.sleep(10*1000);
socket.send(replyPacket);
//socket.close();
}
}
catch (SocketException e)
{
e.printStackTrace();
}
catch (IOException i)
{
i.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) throws ClassNotFoundException, IOException
{
UDPServer server = new UDPServer();
server.createAndListenSocket();
}
}

You want
1 - client to send message to server if it is up/alive
2 - and for server to send some message to all client if it receives signal right?
I am not sure but you can try this,
InetAddress IPAddress = incomingPacket.getAddress();
int port = incomingPacket.getPort();
as you are getting IP address of one client you can store address of all clients on server side which are up/alive in a List or array. Then if you receives signal to server use that list to send respond.
You will need to update list according to up/alive clients.

Related

Sending Unicast packets to a Multicast port

I have a Multicast socket open and is receiving Multicast message. From this thread, it seems that the same multicast socket should also be able to receive unicast messages. However, I'm not able to get anything.
Edit: the port number seems the be problem. Port 3702 is used by ws-discovery for unicasting which is related to what I'm trying to do. I'm tracking down a problem where the client's probe to the service is not caught by the service's multicast socket. I'm running this on windows.
My multicast server:
class Server extends Thread {
MulticastSocket multicastSocket;
final Logger LOG;
final int PORT = 3702;
final String MULTICAST_ADDR = "239.255.255.250";
InetAddress multicastGroup;
public Server() {
LOG = Logger.getLogger("Server");
try {
multicastGroup = InetAddress.getByName(MULTICAST_ADDR);
multicastSocket = new MulticastSocket(PORT);
multicastSocket.setInterface(InetAddress.getLocalHost());
multicastSocket.joinGroup(multicastGroup);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
while (!Global.exit) {
byte[] buf = new byte[1000];
DatagramPacket recv = new DatagramPacket(buf, buf.length);
try {
multicastSocket.receive(recv);
String msg = new String(recv.getData(), StandardCharsets.UTF_8);
LOG.log(Level.INFO, "got: " + msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the client code:
public void directMsgTest(){
try {
DatagramSocket datagramSocket = new DatagramSocket( 8080,InetAddress.getLocalHost());
String msg = "direct msg";
byte[] buf = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), DST_PORT);
datagramSocket.send(packet);
datagramSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
It seems that this is Window's fault. It uses WS discovery in some of its services, thus using port 3702 and eating unicast packets send to port 3702 instead of giving it to my server.
I tried running this on Linux and it was fine.

How to group 2 udp clients?

What i'm trying to do is group 2 clients and make them communicate with eachother. So if 2 clients are connected they would only be able to communicate with eachother and if a third client got connected it would not be able to communicate with the 2 other clients but it would create another group of 2 clients and so on... Right now if a client sends a message it send it over to all clients but i don't know how to make it work like described above. Messages are send from client by typing something in console.
server:
public class Server extends Thread{
public final static int PORT = 7331;
private final static int BUFFER = 1024;
private DatagramSocket socket;
private ArrayList<InetAddress> clientAddresses;
private ArrayList<Integer> clientPorts;
private HashSet<String> existingClients;
public Server() throws IOException {
socket = new DatagramSocket(PORT);
System.out.println("[SERVER] UDP server successfully launched on port " + PORT);
clientAddresses = new ArrayList<InetAddress>();
clientPorts = new ArrayList<Integer>();
existingClients = new HashSet<String>();
}
public void run() {
byte[] buf = new byte[BUFFER];
while (true) {
try {
//resets buffer so only new messages get displayed
Arrays.fill(buf, (byte) 0);
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String content = new String(buf, buf.length);
InetAddress clientAddress = packet.getAddress();
int clientPort = packet.getPort();
String id = clientAddress.toString() + "," + clientPort;
if (!existingClients.contains(id)) {
existingClients.add(id);
clientPorts.add(clientPort);
clientAddresses.add(clientAddress);
}
System.out.println(id + " : " + content);
byte[] data = (id + " : " + content).getBytes();
for (int i = 0; i < clientAddresses.size(); i++) {
InetAddress cl = clientAddresses.get(i);
int cp = clientPorts.get(i);
packet = new DatagramPacket(data, data.length, cl, cp);
socket.send(packet);
}
} catch (Exception e) {
System.err.println(e);
}
}
}
public static void main(String args[]) throws Exception {
Server s = new Server();
s.start();
}
}
clients:
public class Client implements Runnable {
public static void main(String args[]) throws Exception {
String host = "127.0.0.1";
DatagramSocket socket = new DatagramSocket();
//handles the receiving part for every client (incoming packets to clients)
MessageReceiver r = new MessageReceiver(socket);
Client s = new Client(socket, host);
Thread rt = new Thread(r);
Thread st = new Thread(s);
rt.start();
st.start();
}
public final static int PORT = 7331;
private DatagramSocket sock;
private String hostname;
Client(DatagramSocket s, String h) {
sock = s;
hostname = h;
}
//sending clients socket to server
private void sendMessage(String s) throws Exception {
//getting bytes from message
byte buf[] = s.getBytes();
//getting hostname from server
InetAddress address = InetAddress.getByName(hostname);
//setting up packet
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, PORT);
//sending packet to server
sock.send(packet);
}
public void run() {
//connected boolean is used to send a greetings message once for every new client that has joined
boolean connected = false;
do {
try {
sendMessage("GREETINGS");
connected = true;
} catch (Exception e) {
}
} while (!connected);
//reads from the console
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while (true) {
try {
while (!in.ready()) {
Thread.sleep(100);
}
//sends message from console to server
sendMessage(in.readLine());
} catch (Exception e) {
System.err.println(e);
}
}
}
}
//this class handles receiving part of clients
class MessageReceiver implements Runnable {
DatagramSocket sock;
byte buf[];
MessageReceiver(DatagramSocket s) {
sock = s;
buf = new byte[1024];
}
public void run() {
while (true) {
try {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
sock.receive(packet);
String received = new String(packet.getData(), 0,
packet.getLength());
System.out.println(received);
} catch (Exception e) {
System.err.println(e);
}
}
}
}
What youre trying is a message broadcast or a message-repeater-client.
broadcasting is implemented on network layer (using brodcast the local network broadcast adress).
And if you implementing it that way, you'll flood your network, when you have more than 2 clients. Best regards to your network admin. ;-)

Android UDP socket

Hi there currently i am creating a UDP connection for my program currently its localhost how am i going to insert my IP address so that another computer in the same network will be able to receive the message i type at the server side.
UDPSERVER
package testing;
import java.io.*;
import java.net.*;
public class UdpServer {
public static void main(String args[]) {
String str;
try {
BufferedReader Br;
Br = new BufferedReader(new InputStreamReader(System. in ));
DatagramSocket Sock;
Sock = new DatagramSocket(1000);
DatagramPacket Dp;
System.out.println("Enter the data..... Enter 'exit' to stop");
while (true) {
str = Br.readLine();
Dp = new DatagramPacket(str.getBytes(), str.length(),
InetAddress.getByName("localhost"), 2000);
Sock.send(Dp);
if (str.equals("exit")) break;
}
Sock.close();
} catch (Exception e) {}
}
}
UdpClient
package testing;
import java.net.*;
public class UdpClient {
public static void main(String arg[]) {
String str;
DatagramSocket Sock;
DatagramPacket Dp;
try {
Sock = new DatagramSocket(2000);
byte Buff[] = new byte[1024];
System.out.println("Client ready...");
while (true) {
Dp = new DatagramPacket(Buff, 1024);
Sock.receive(Dp);
str = new String(Dp.getData(), 0, Dp.getLength());
System.out.println(str);
if (str.equals("exit")) break;
}
Sock.close();
} catch (Exception e) {
System.out.println("Connection failure...");
} finally {
System.out.println("Server Disconnected...");
}
}
}
The first step is to try and hardcode the ip of the other computer and test. If that works then look at adding UDP Broadcast Discovery. Here's an example in java:
http://michieldemey.be/blog/network-discovery-using-udp-broadcast/
The idea is that all devices that need to talk broadcast on UDP. Once they hear the broadcast, they need to connect to eachother. Usually one side will need to be pre-determined as the server, and the other as the client.

Creating Java Proxy MITM

I'm trying to create a Java program as a proxy to view packets from an incoming source to debug. To do this, I have created a simple Java server application and have edited my host file on the device. Everything works fine as of now, (even my Relay class file) but I am trying to make it into a full fledged proxy. How could I incorporate elements to send data to the server, and send the response back to the client? Sort of like a Man-In-The-Middle type of thing.
import java.net.*;
import java.io.*;
import org.ini4j.Ini;
public class RelayMultiClient extends Thread {
private Socket socket = null;
Socket relay = null;
public RelayMultiClient(Socket socket) {
super("RelayMultiClient");
this.socket = socket;
}
public void run() {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
if(Relay.max_clients == Relay.connected_clients) {
//There are too many clients on the server.
System.out.println("Connection refused from " + socket.getRemoteSocketAddress() + ": Too many clients connected!");
out.close();
in.close();
socket.close();
}
else {
Ini ini = new Ini(new File("settings.ini"));
Relay.connected_clients++;
System.out.println("Connection from client " + socket.getRemoteSocketAddress() + " established. Clients Connected: " + Relay.connected_clients);
while (in.readLine() != null) {
//Send data to the server
//Receive data from server and send back to client
}
System.out.println("Connection from client " + socket.getRemoteSocketAddress() + " lost.");
Relay.connected_clients--;
out.close();
in.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks,
Chris
P.S: I'm not attempting to get HTTP data, I am trying to get data from a game I have created. I don't know if this type of data requires any extra handling.
How could I incorporate elements to send data to the server, and send the response back to the client?
Try the following example as basic proxy:
public class Proxy {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(1230); // proxy port
Socket socket = serverSocket.accept();
Socket relay = new Socket("localhost", 1234); // server address
new ProxyThread(relay.getInputStream(), socket.getOutputStream()).start();
new ProxyThread(socket.getInputStream(), relay.getOutputStream()).start();
}
}
class ProxyThread extends Thread {
private InputStream inputStream;
private OutputStream outputStream;
ProxyThread(InputStream inputStream, OutputStream outputStream) {
this.inputStream = inputStream;
this.outputStream = outputStream;
}
public void run() {
try {
int i;
while ((i = inputStream.read()) != -1) {
outputStream.write(i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
It lacks proper exception handling, only demonstrating the basic idea.

Implementation of a simple file transfer client server

Hi I have the following code to the client - server through the thread, I have a errors,
Can't setup server on this port number.
Can't setup server on this port number.
but why?
class client:
import java.io.*;
import java.net.Socket;
// create class client
public class Client extends Thread {
Socket socket = null;
Socket socket1 = null;
// create send method
public void sendFile() throws IOException {
String host = "127.0.0.1";
String host1 = "127.0.0.2";
socket = new Socket(host, 4444);
socket1 = new Socket(host1, 444);
File file = new File("/home/reza/Desktop/link help");
File file1 = new File("/home/reza/Desktop/hi");
long length = file.length();
long length1 = file1.length();
byte[] bytes = new byte[(int) length];
byte[] bytes1 = new byte[(int) length1];
FileInputStream fis = new FileInputStream(file);
FileInputStream fis1 = new FileInputStream(file1);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
BufferedInputStream bis1 = new BufferedInputStream(fis1);
BufferedOutputStream out1 = new BufferedOutputStream(socket1.getOutputStream());
int count;
int count1;
while ((count = bis.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
while ((count1 = bis1.read(bytes1)) > 0) {
out1.write(bytes1, 0, count1);
}
Thread t = new Thread(new Runnable() {
public void run()
{
while(socket.isConnected())
{
Wait2();
try {
sendFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
Thread t1 = new Thread(new Runnable() {
public void run() {
while(socket1.isConnected())
{
Wait2();
try {
sendFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
t.start();
t1.start();
fis.close();
fis1.close();
out.close();
bis.close();
out1.close();
bis1.close();
socket.close();
socket1.close();
}
public void Wait2()
{
try {
Thread.currentThread().sleep(3000);
} catch (InterruptedException x) {
System.out.println("Interrupted!");
}
}
}
// class server
import java.io.*;
import java.net.*;
public class Server {
public void recivefile() throws IOException {
ServerSocket serverSocket = null;
ServerSocket serverSocket1 = null;
try {
serverSocket = new ServerSocket(4444);
//serverSocket1 = new ServerSocket(444);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number. ");
}
try {
serverSocket1 = new ServerSocket(444);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number. ");
}
Socket socket = null;
Socket socket1 = null;
InputStream is = null;
InputStream is1 = null;
FileOutputStream fos = null;
FileOutputStream fos1 = null;
BufferedOutputStream bos = null;
BufferedOutputStream bos1 = null;
int bufferSize = 0;
int bufferSize1 = 0;
try {
socket = serverSocket.accept();
socket1 = serverSocket1.accept();
} catch (IOException ex) {
System.out.println("Can't accept client connection. ");
}
try {
is = socket.getInputStream();
is1 = socket1.getInputStream();
bufferSize = socket.getReceiveBufferSize();
bufferSize1 = socket1.getReceiveBufferSize();
System.out.println("Buffer size: " + bufferSize);
System.out.println("file recieved");
System.out.println("Buffer size1: " + bufferSize1);
System.out.println("file recieved");
System.out.println("file recieved");
} catch (IOException ex) {
System.out.println("Can't get socket input stream. ");
}
try {
fos = new FileOutputStream("/home/reza/Desktop/reza");
bos = new BufferedOutputStream(fos);
fos1 = new FileOutputStream("/home/reza/Desktop/ali");
bos1 = new BufferedOutputStream(fos1);
} catch (FileNotFoundException ex) {
System.out.println("File not found. ");
}
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
}
byte[] bytes1 = new byte[bufferSize1];
int count1;
while ((count1 = is1.read(bytes1)) > 0) {
bos1.write(bytes1, 0, count1);
}
bos.flush();
bos.close();
bos1.flush();
bos1.close();
is.close();
is1.close();
socket.close();
serverSocket.close();
socket1.close();
serverSocket1.close();
}
public static void main(String[] args) throws IOException
{
System.out.println("server is run, please send file");
Server s = new Server();
s.recivefile();
}
}
error is :
Can't setup server on this port number.
Can't setup server on this port number.
You can't start a server on 127.0.0.2 - therein lies your problem.
netstat -ano | find "1024"
try above command if you are running your java files on windows environment that will help you to find any process using same port no as yours and also use
ex.printStackTrace() along with
System.out.println("Can't setup server on this port number.");
Assuming that your code runs on a unix platform, your server code is trying twice to open a socket on port 444, which is a system reserved port. In order to be able to succeed, your programme must run with administrative priviledges, and you must ensure that the port is not already used by another process.
A possible workaround is to:
use a port above 1024. These ports are free to use for userland programmes
in case of failure have a backup port, also above 1024. You must amend both server and client codes to try both ports, and of course your communication protocol must include some form of handshaking to make sure they are talking to the right interlocutor.
There are many other problems with your code listed in other answers.
you don't need to make every objects twice. Only one instance is enough in most cases,
if your server is running continuously and must accept many connections, you should not close the accepting socket at the end of one receiving session.
also the server is supposed to run a loop on the server socket accept call, and start a new thread for each incoming connection, whose job is to handle that connection.
While I understand your willingness to learn and experiment, there are existing solutions to what you are trying to achieve. For instance, you could simply use a FTP server for your purpose.
The way you have written client - server program is wrong I guess.
Following are the mistakes you have done...
1) In Client class, you have sendFile function in which you've created two threads - t & t1. In run function you are again calling the same sendFile function.
So it keeps creating threads under threads just like recursion.
2) In Server class, you are listening to two port within the same recieveFile function. As the socket = serverSocket.accept() is a blocking call, It wont excecute the rest of the code untill it finds a single client to connect.
So what exactly happens here is.. Once the first client connects, thenafter immediately it expects second client to connect.
In the mean time your client thread may try to access the port on which connection has not been established.
In short, your SERVER SHOULD BE IN A THREADING ENVIRONMENT NOT THE CLIENT.
And I would suggest that for different port you should use different server.
i.e. create different server class for both 1024 & 1025 port.

Categories