same server listening on different sockets - java

I have a UDP multicast server listening on 2 sockets on 2 different ports. I achieved listening on these 2 sockets from clients. But i want to identify on which socket a client is sending a packet. Since my problem is that ; on the server if I listen on socket(9999) and if the client is sending on socket(8888) then at the server side I want it to identify the incoming packet is from which port.
public class MulticastReceiver
{
public static void main(String[] args)
{
MulticastSocket socket = null;
DatagramPacket packet = null;
MulticastSocket soc = null;
byte[] inBuf = null;
try
{
socket = new MulticastSocket(8888);
soc = new MulticastSocket(9999);
InetAddress address = InetAddress.getByName("224.2.2.3");
socket.joinGroup(address);
soc.joinGroup(address);
System.out.println("224.2.2.3 ready to receive packets");
while(true)
{
inBuf=new byte[256];
packet = new DatagramPacket(inBuf,inBuf.length);
System.out.println("port is: "+ packet.getAddress() + packet.getPort());
if(packet.getPort() == 9999)
{
soc.receive(packet);
//System.out.println("Data at 224.2.2.3:: " + new String(packet.getData()));
}
else
socket.receive(packet);
System.out.println("Data at 224.2.2.3:: " + new String(packet.getData()));
}
}
catch(Exception e)
{
}
}
}
public class MulticastSender {
public static void main(String[] args) {
DatagramSocket socket = null;
DatagramPacket outPacket = null;
byte[] outBuf;
final int PORT = 8888;
try {
socket = new DatagramSocket();
long counter = 0;
String msg;
msg = "This is multicast! ";
outBuf = msg.getBytes();
//Send to multicast IP address and port
InetAddress address = InetAddress.getByName("224.2.2.3");
outPacket = new DatagramPacket(outBuf, outBuf.length, address, PORT);
socket.send(outPacket);
System.out.println("Server sends : " + msg);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
} catch (IOException ioe) {
System.out.println(ioe);
}
}
}
public class AnotherSender {
public static void main(String[] args) {
DatagramSocket socket = null;
DatagramPacket outPacket = null;
byte[] outBuf;
final int PORT = 9999;
try {
socket = new DatagramSocket();
long counter = 0;
String msg;
msg = "This is another multicast! " + counter;
counter++;
outBuf = msg.getBytes();
//Send to multicast IP address and port
InetAddress address = InetAddress.getByName("224.2.2.3");
outPacket = new DatagramPacket(outBuf, outBuf.length, address, PORT);
socket.send(outPacket);
System.out.println("Server sends : " + msg);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
} catch (IOException ioe) {
System.out.println(ioe);
}
}
}

Your code doesn't make sense. The packet won't have a port number at all until you put one into it or receive() does, and at best this will just read alternately between the two sockets, blocking each time, possibly forever, receiving from one socket, and thus starving the other one.
You need a receiving thread for each non-blocking socket.

Related

Receive message from multicast socket on another host (from aws server instance)

I want to send/receive messages by the multicast socket.
This is my code
'''
public class MulticastSender {
public static final String GROUP_ADDRESS = "230.0.0.1";
public static final int PORT = 7766;
public static void main(String[] args) throws InterruptedException {
DatagramSocket socket = null;
try {
// Get the address that we are going to connect to.
InetAddress address = InetAddress.getByName(GROUP_ADDRESS);
System.out.println("GROUP_ADDRESS: " + address);
// Create a new Multicast socket
socket = new DatagramSocket();
DatagramPacket outPacket = null;
long counter = 0;
while (true) {
String msg = "Sent message No. " + counter;
counter++;
outPacket = new DatagramPacket(msg.getBytes(), msg.getBytes().length, address, PORT);
socket.send(outPacket);
System.out.println("Server sent packet with msg: " + msg);
Thread.sleep(1000); // Sleep 1 second before sending the next message
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (socket != null) {
socket.close();
}
}
}
'''
'''
public class MulticastReceiver {
public static final byte[] BUFFER = new byte[4096];
public static void main(String[] args) {
MulticastSocket socket = null;
DatagramPacket inPacket = null;
try {
// Get the address that we are going to connect to.
SocketAddress address = new InetSocketAddress(MulticastSender.GROUP_ADDRESS, MulticastSender.PORT);
// Create a new Multicast socket
socket = new MulticastSocket(address);
socket.joinGroup(address, NetworkInterface.getByName("eth0"));
while (true) {
// Receive the information and print it.
inPacket = new DatagramPacket(BUFFER, BUFFER.length);
socket.receive(inPacket);
// System.out.println(socket.getInterface());
String msg = new String(BUFFER, 0, inPacket.getLength());
System.out.println("From " + inPacket.getAddress() + " Msg : " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
'''
It is working on my local host. however, I want to send messages from my AWS server instance (with public ipv4) and receive them in the local client. How to do it?
if yes, please give me an example!
Tks all

How to run 2 main methods in parallel threads?

I have two following classes (including only main methods for simplicity)
public class UDPServer {
public static void main(String[] args) throws IOException {
int serverPort = 9876;
DatagramSocket socket = new DatagramSocket(serverPort);
byte[] buffer = new byte[1024];
boolean isConnected = true;
while (isConnected) {
try {
DatagramPacket request = new DatagramPacket(buffer, buffer.length);
socket.receive(request);
DatagramPacket reply = new DatagramPacket(
request.getData(),
request.getLength(),
request.getAddress(),
request.getPort()
);
socket.send(reply);
} catch (IOException ex) {
isConnected = false;
Logger.getLogger(UDPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class UDPClient {
public static void main(String[] args) {
String pathToQuery = getUserInput();
List<Packet> queried = UDPServer.getQueriedServerDataTypes(pathToQuery);
try {
if (args.length < 1) {
System.out.println("Usage: UDPCLient <msg> <server host name>");
System.exit(-1);
}
// Create a new datagram socket
DatagramSocket socket = new DatagramSocket();
// Preferred IPv4 address (cmd: ipconfig/all)
InetAddress host = InetAddress.getByName(args[0]);
int serverPort = 9876;
for (int i = 0; i < queried.size(); i++) {
Packet dataType = queried.get(i);
String requestFile = "data_type_request_v" + (i + 1) + ".txt";
UDPServer.saveToFile(
dataType,
"Server request.",
requestFile
);
// Serialize Packet object to an array of bytes
byte[] data = Tools.serialize(dataType);
System.out.println("Sent: " + Arrays.toString(data));
// Request datagram packet will store data query for the server
DatagramPacket request = new DatagramPacket(
Objects.requireNonNull(data),
data.length,
host,
serverPort
);
// Send serialized datagram packet to the server
socket.send(request);
// The reply datagram packet will store data returned by the server
DatagramPacket reply = new DatagramPacket(data, data.length);
System.out.println("Reply: " + Arrays.toString(reply.getData()));
// Acquire data returned by the server
socket.receive(reply);
// Store deserialized data in null Packet object.
Packet read = (Packet) Tools.deserialize(data);
System.out.println("Reading deserialized data...\n" + read.toString());
String responseFile = "data_type_response_v" + (i + 1) + ".txt";
UDPServer.saveToFile(
read,
"Server response.",
responseFile
);
boolean isResponseEqualRequest = UDPServer.isResponseEqualRequest(
requestFile,
responseFile
);
if (isResponseEqualRequest) {
System.out.println("Communication successful. Server response corresponds to the request.");
} else {
System.out.println("Communication unsuccessful. Server response does not correspond to the request.");
}
}
// Close the datagram socket
socket.close();
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(UDPClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
In order for the UDPClient to work properly, UDPServer has to be running in the background. I want to run the UDPServer.main() in parallel thread and as soon as UDPClient.main() finishes, the thread should terminate as well.
How do I do that?

How do i receive data

My listener ->
public void startListening(){
String[] details = session.split(":");
SessionUser user = new SessionUser();
System.out.println("Waiting for another user..");
listening = new Thread("listen thread"){
public void run() {
while(true) {
while (user.users < 2) {
try {
Socket socket1 = socket.accept();
System.out.println(socket1.getInetAddress().toString() + " has joined...");
user.users++;
socket1.close();
} catch (Exception e) {
System.out.println("Ran into a error!");
}
}
}
}
};
listening.start();
}
My sender ->
public void join(InetAddress address, int port){
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
try {
DatagramSocket socket = new DatagramSocket();
System.out.println("Attempting to join session <" + address.toString() + ":" + port + ">!");
socket.send(packet);
System.out.println("Joining......");
}catch (Exception e){
System.out.println("Unable to connect, this may be a server error, or you've entered incorrect details!");
}
}
So i just want to send packets to the hosts server upon connecting, however, when i run this i am not seeing any sort of output, here is a picture that will probably explain it better then i can -> click me
Change your server to receive the packets as well
DatagramSocket serverSocket = new DatagramSocket(port);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
serverSocket.receive(packet); // This will block until a packet is received
System.out.println("Received: " + new String(packet.getData()));
Try testing with your client
public void join(InetAddress address, int port){
byte[] data = "Hello".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
try {
DatagramSocket socket = new DatagramSocket();
System.out.println("Attempting to join session <" + address.toString() + ":" + port + ">!");
socket.send(packet);
System.out.println("Joining......");
}catch (Exception e){
System.out.println("Unable to connect, this may be a server error, or you've entered incorrect details!");
}
}
If you need to maintain a connection, it's better to use TCP with Sockets.
In your receiver, you're reading from a TCP socket, whereas your sender is sending an UDP packet. This cannot work.

A problem about Java UDP communication with multi thread

I'm studying java network programming now and i wrote a program that the client sends 30 times current time to Server and the Server will create a new thread to parse the received UDP packet and give feedback to Client if Server receives the UDP packet.
The question is, after I run my code, the Server can receive the UDP packet and create a new thread, but it seems like DatagramSocket and DatagramPacket don't pass to the thread. Thence the thread can't give a feedback to Client and Client will wait all the time after send the first UDP packet.
My code is here:
Server
public class MulUDPServer {
public static void main(String[] args) {
DatagramSocket socket = null;
DatagramPacket receivedPacket;
final int PORT = 10010;
byte[] b = new byte[1024];
receivedPacket = new DatagramPacket(b, b.length);
try {
socket = new DatagramSocket(PORT);
System.out.println("Server start!");
while (true) {
// receive the packet from server
socket.receive(receivedPacket);
// to check if Server get the packet
System.out.println(new String(receivedPacket.getData(), 0, receivedPacket.getLength()));
// start the thread to handle the packet we have got
Thread thread = new Thread(new LogicThread(socket, receivedPacket));
thread.start();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// close the connection
socket.close();
} catch (Exception e) {
}
}
}
Thread
public class LogicThread implements Runnable {
DatagramSocket socket = null;
DatagramPacket receivedPacket = null;
public LogicThread(DatagramSocket socket, DatagramPacket receivedPacket) {
this.socket = socket;
this.receivedPacket = receivedPacket;
}
public void run() {
try {
// to test if a thread have been set up
System.out.println("a thread have been set up");
byte[] data = receivedPacket.getData();
int len = receivedPacket.getLength();
// get the client IP
InetAddress clientAddress = receivedPacket.getAddress();
// get the client port
int clientPort = receivedPacket.getPort();
// print the info about received packet
System.out.println("Client's IP:" + clientAddress.getHostAddress());
System.out.println("Client's port:" + clientPort);
System.out.println("The info:" + new String(data, 0, len));
// feedback to Client
byte[] b = "OK".getBytes();
DatagramPacket sendPacket = new DatagramPacket(b, b.length, clientAddress, clientPort);
// send
socket.send(sendPacket);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Client
public class MulUDPClient {
public static void main(String[] args) {
DatagramSocket socket = null;
DatagramPacket sendPacket;
DatagramPacket receivedPacket;
String serverHost = "localhost";
int serverPort = 10010;
try {
socket = new DatagramSocket();
InetAddress address = InetAddress.getByName(serverHost);
byte[] b = new byte[1024];
receivedPacket = new DatagramPacket(b, b.length);
System.out.println("Client ready!");
for (int i = 0; i < 30; i++) {
// get the current time
Date d = new Date();
String content = d.toString();
byte[] data = content.getBytes();
sendPacket = new DatagramPacket(data, data.length, address, serverPort);
socket.send(sendPacket);
System.out.println("already send time");
Thread.sleep(10);
// receive packet from Server
socket.receive(receivedPacket);
byte[] response = receivedPacket.getData();
int len = receivedPacket.getLength();
String s = new String(response, 0, len);
System.out.println("the feedback from Server:" + s);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// close the connection
socket.close();
} catch (Exception e) {
}
}
}
}
the **Result** after run the Server and Client separately in two terminals:
Server
Server start!
Fri Nov 23 14:52:02 CST 2018
a thread have been set up
Client
Client ready!
already send time
From the result we can know, the Client have send a UDP packet and the Server parse it correctly and create a thread. Then the program is waiting...
It puzzle me a few days, Can anyone help me to solve it? :). Thanks!
Edit
Client
**CAN NOT** work
for (int i = 0; i < 30; i++) {
Thread writerWorker = new WriterWorker(socket);
writerWorker.start();
Thread readerWorker = new ReaderWorker(socket);
readerWorker.start();
}
**CAN** work
for (int i = 0; i < 30; i++) {
Date d = new Date();
String content = d.toString();
byte[] data = content.getBytes();
sendPacket = new DatagramPacket(data, data.length, address, serverPort);
socket.send(sendPacket);
Thread.sleep(10);
Thread readerWorker = new ReaderWorker(socket);
readerWorker.start();
}
WriterWorker
public class WriterWorker extends Thread {
DatagramSocket socket;
String serverHost = "localhost";
int serverPort = 10000;
DatagramPacket sendPacket;
public WriterWorker(DatagramSocket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
InetAddress address = InetAddress.getByName(serverHost);
Date d = new Date();
String content = d.toString();
byte[] data = content.getBytes();
sendPacket = new DatagramPacket(data, data.length, address, serverPort);
socket.send(sendPacket);
System.out.println("already send time");
} catch (Exception e) {
// TODO: handle exception
}
}
}
there is a flaw in your logic, when you do socket.receive(receivedPacket); this will let the worker wait until some datagramm packets does arrive...
the right way to handle asynchron communication via sockets would be the following (here an example for client side)
socket = new DatagramSocket();
Thread readerWorker = new ReaderWorker(socket);
readerWorker.start();
Thread writerWorker = new WriterWorker(socket);
writerWorker.start();
that way you would seperate reading and writing into different threads and the blocking methode socket.receive(...) would not stop your writing thread...
each worker would implement it's own worker loop
writer loop:
while(true){
if (sendPacket!= null){
socket.send(sendPacket);
}
Thread.sleep(10);
}
reader loop:
while(true){
socket.receive(receivedPacket);
handlePacket(receivedPacket);
}
NOTE:
that code was written totally out of my mind i didn't check proper syntax
delete the "Thread.sleep(10)" in client

Implementing a simple UDP network that continuously broadcasts to its neighbours

I have 3 nodes A, B and C with their respective port numbers.
I'm trying to write a java program that takes in 3 arguments:
its node name and its 2 neighboring node's ports and broadcasts a string "Hello I'm A" to them (so A would broadcast to B and C). It will do this every 3 seconds.
This program will be run in 3 separate instances.
Upon receiving a string it will print what node it has received it from "Received string" (example for Port B).
I have difficulties implementing this, I have heard of something called multicasting with UDP though. Here is my work so far, what am I doing wrong?
class UDP {
public static void main(String[] args) throws Exception {
String nodeName = args[0];
int neighbourPort1 = Integer.valueOf(args[1]);
int neighbourPort2 = Integer.valueOf(args[2]);
while(true) {
Thread.sleep(3000); //every 3 seconds
//Continously broadcast and listen to neighbour1
DatagramSocket socket1 = null;
try {
//CREATE SOCKET TO NEIGHBOUR1
InetAddress host = InetAddress.getByName("localhost");
socket1 = new DatagramSocket();
socket1.connect(host, neighbour1);
//CREATE DATAGRAMS FOR SENDING
String message = "Hello I'm " + nodeName;
byte[] sendData = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, host, port);
socket1.send(sendPacket);
//CREATE DATAGRAMS FOR RECEIVING
byte[] receiveData = new byte[100]; //is there a way to determine the needed space?
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket1.receive(receivePacket);
System.out.println("Received string");
} catch(Exception e) { }
//Do the same for neighbour2, code is basically identical except for variables
DatagramSocket socket2 = null;
try {
//CREATE SOCKET TO NEIGHBOUR2
InetAddress host = InetAddress.getByName("localhost");
socket2 = new DatagramSocket();
socket2.connect(host, neighbour2);
//FOR SENDING DATAGRAMS
String message = "Hello I'm " + nodeName;
byte[] sendData = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, host, port);
socket2.send(sendPacket);
//FOR RECEIVING DATAGRAMS
byte[] receiveData = new byte[100]; //is there a way to determine the needed space?
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket2.receive(receivePacket);
System.out.println("Received string");
} catch(Exception e) { }
}
}
}
I know I'm close to the solution. I'm able to broadcast properly but it's the constantly listening part that gets me.
I think its best to use a separate Thread to listen for data on your own port.
A sends data to B and blocks until it gets a packet from B.
B sends data to C and blocks until it gets a packet from C.
C sends data to A and blocks until it gets a packet from A.
Every node is waiting for each other. Just send the packets and wait 3 seconds.
The other thread is going to listen only.
public class UDP {
public static void main(String[] args) throws Exception {
final String nodeName = args[0];
final int ownPort = Integer.valueOf(args[1]);
final int neighbourPort1 = Integer.valueOf(args[2]);
final int neighbourPort2 = Integer.valueOf(args[3]);
// Don't create a new socket every time
DatagramSocket neighbour1 = new DatagramSocket();
DatagramSocket neighbour2 = new DatagramSocket();
neighbour1.connect(InetAddress.getLocalHost(), neighbourPort1);
neighbour2.connect(InetAddress.getLocalHost(), neighbourPort2);
// You have to LISTEN
new Thread() {
#Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket(ownPort);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
// Blocks until it gets a packet
socket.receive(packet);
System.out.println("Received string");
}
// socket.close();
} catch (final Exception e) {
e.printStackTrace();
}
}
}.start();
while (true) {
Thread.sleep(3000);
sendPacket(neighbour1, nodeName);
sendPacket(neighbour2, nodeName);
}
// If you're not using an infinite loop:
// neighbour1.close();
// neighbour2.close();
}
private static void sendPacket(DatagramSocket to, String from) throws Exception {
String message = "Hello I'm " + from;
byte[] data = message.getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length);
to.send(packet);
}
}
Here is a simple frame for a server with two threads, one writing and one reading, place your network code at the right places.
package testing;
import java.util.Scanner;
public class ThreadTest {
public class MyListenerThread extends Thread {
#Override
public void run() {
/*
* Open Datagram ...
*/
while (true) {
/*
* Read data ...
*/
Scanner scanner = new Scanner(System.in);
System.out.println("read: " + scanner.next());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MySenderThread extends Thread {
#Override
public void run() {
/*
* Open Multicast ...
*/
while (true) {
/*
* Send ...
*/
System.out.println("Send ...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void start() {
MyListenerThread listener = new MyListenerThread();
MySenderThread sender = new MySenderThread();
listener.start();
sender.start();
}
public static void main(String[] args) {
ThreadTest server = new ThreadTest();
server.start();
}
}

Categories

Resources