UDP Server/Client for Game - java

I am trying to put together a tank game and I am having issues with the networking part. What am I doing wrong on the server??
Here is my server code :
import java.io.*;
import java.net.*;
class UDPServer extends Thread{
private DatagramSocket socket;
private TanksComponent tank;
private InetAddress IPAddress;
private int port = 9876;
public void UPDServer() throws IOException{
socket = new DatagramSocket(port);
}
public void run(){
while(true){
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("RECEIVED: " + packet.getAddress() + " " + packet.getPort() + ": " + new String(packet.getData()) ) ;
IPAddress = packet.getAddress();
}
}
public void sendData(byte[] data){
DatagramPacket packet = new DatagramPacket(data, data.length, IPAddress, port);
try {
this.socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is my client code :
import java.io.*;
import java.net.*;
class UDPClient extends Thread{
private InetAddress ipAddress;
private DatagramSocket clientSocket;
private TanksComponent tank;
private byte[] data = new byte[1024];
private int port = 9876;
public UDPClient(TanksComponent tanksComponent) throws SocketException, UnknownHostException{
this.tank = tanksComponent;
this.clientSocket = new DatagramSocket();
this.ipAddress = InetAddress.getLocalHost();
}
public void run(){
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
clientSocket.receive(packet);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String message = new String(packet.getData());
System.out.println("SERVER > " + message);
}
public void sendData(byte[] data){
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port);
try {
clientSocket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am invoking the code like this :
public void start() throws UnknownHostException, SocketException {
if(JOptionPane.showConfirmDialog(this, "Server") == 0){
socketServer = new UDPServer();
socketServer.start();
}else{
socketClient = new UDPClient(this);
socketClient.start();
System.out.println("Send");
socketClient.sendData("ping".getBytes());
}
Thanks for the help kind stranger !

I don't have a ton of experience with Java networking but feel free to look at a project I've been working on recently:
server
client

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 get Java sockets work with public IP on google cloud

I'm planning to create a server and run it on google cloud VM, this code is working fine in the localhost but it won't run on External IP.
import java.net.*;
import java.io.*;
public class Server extends Thread {
private ServerSocket serverSocket;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void run() {
while(true) {
try {
System.out.println("Waiting for Connection ");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Goodbye");
server.close();
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String [] args) throws UnknownHostException {
int port = 4999;
try {
Thread t = new Server(port);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and this is for the client
import java.net.*;
import java.io.*;
public class Client {
public static void main(String [] args) {
String serverName = "localhost";
int port = Integer.parseInt("4999");
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("[Client]Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("[Server] " + in.readUTF());
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and this is the net config of the google VM instance:
Internal ip-> 10.138.0.13 (nic0) | External ip-> 34.83.94.126
can you please tell me how to get it running on a public ip.

Server alternates between users instead of broadcasting

I have been working on a message system where users type in a server IP/Port and that server then takes in messages and relays them to all other users on the server. The whole program was based of a echo server i rewrote from scratch, for every server.accept() socket it creates two Threads, one to receive messages and one to send them back. The two Threads are connected by a DatagramPacket system so if the server receives a message from one socket it sends it back to all other users because their Threads are listening for the same thing, this is where i am encountering problems; everything work fine except the fact that the user who receives the message alternates in order to time of log on.
Example of problem when two clients are connected:
Client #1 sends 10 messages:
0
1
2
3
4
5
6
7
8
9
The Server receives all of them.
Client #1 receives:
1
3
5
7
9
Client #2 receives:
0
2
4
6
8
Here is the code for the Client:
import java.io.*;
import java.util.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MessageClient {
public static void main(String[] args) {
System.out.println("Starting Message System...");
Scanner in = new Scanner(System.in);
MessageClient mc = new MessageClient();
String input;
System.out.println(":System Started, type help for help.");
System.out.print(":");
while (true) {
input = in.nextLine();
if (input.equalsIgnoreCase("HELP")) {
mc.printHelp();
System.out.print(":");
} else if (input.equalsIgnoreCase("QUIT")) {
System.exit(0);
} else if (input.equalsIgnoreCase("CONNECT")) {
mc.connect(in);
in.nextLine();
System.out.print(":");
} else {
System.out.print("No command found.\n:");
}
}
}
public static void printHelp() {
System.out.println("help\tShow this prompt\nconnect\tStarts a new connection\nquit\tQuit the program\nexit\tExit a connection");
}
public void connect(Scanner in) {
Socket soc = null;
InetAddress addr = null;
System.out.print("IP_ADDRESS/HOST:");
String ip = in.nextLine();
System.out.print("PORT:");
int port = in.nextInt();
try {
System.out.println("Attempting to connect to HOST:\'" + ip + "\' on PORT:\'" + port + "\'");
addr = InetAddress.getByName(ip);
soc = new Socket(addr, port);
} catch(Exception e) {
System.out.println("Error connecting to server: " + e.getLocalizedMessage());
return;
}
SwingUtilities.invokeLater(new MessageGUI(ip + ":" + port, soc));
}
}
class MessageGUI implements Runnable {
public MessageGUI(String windowName, Socket server) {
JFrame window = new JFrame(windowName);
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.setSize(500, 300);
window.setLayout(new BorderLayout());
window.setVisible(true);
MessageReceive mr = new MessageReceive(server);
mr.setEditable(false);
mr.setBackground(new Color(0, 0, 0));
mr.setForeground(new Color(0, 255, 0));
mr.setVisible(true);
new Thread(mr).start();
window.add(mr, BorderLayout.CENTER);
DataOutputStream dos = null;
try {
dos = new DataOutputStream(server.getOutputStream());
} catch(Exception e) {
System.out.println("Error creating output stream to server: " + e.getLocalizedMessage());
}
JTextField input = new JTextField();
input.addActionListener(new MessageSend(server, input, dos));
input.setBackground(new Color(0, 0, 0));
input.setForeground(new Color(0, 255, 0));
window.add(input, BorderLayout.PAGE_END);
System.out.println("Displaying connection.");
}
public void run() {}
}
class MessageReceive extends JTextArea implements Runnable {
protected Socket server;
public MessageReceive(Socket server) {
this.server = server;
}
public void run() {
DataInputStream dis = null;
int bytes;
try {
dis = new DataInputStream(server.getInputStream());
} catch(Exception e) {
System.out.println("Error connecting server: " + e.getLocalizedMessage());
}
this.append("Connected.\n");
while (true) {
try {
while ((bytes = dis.read()) != -1) this.append(String.valueOf((char) bytes));
} catch(Exception e) {
System.out.println("Error reading from server: " + e.getLocalizedMessage());
return;
}
}
}
}
class MessageSend implements ActionListener {
protected Socket server;
protected JTextField input;
protected DataOutputStream dos = null;
public MessageSend(Socket server, JTextField input, DataOutputStream dos) {
this.server = server;
this.input = input;
this.dos = dos;
}
public void actionPerformed(ActionEvent ae) {
try {
dos.writeBytes(input.getText() + "\n");
input.setText("");
} catch(Exception e) {
System.out.println("Error writing to server output stream: " + e.getLocalizedMessage());
}
}
}
Here is the code for the Server:
import java.io.*;
import java.net.*;
import java.util.*;
public class MessageServer {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
MessageServer ms = new MessageServer();
System.out.println("Starting server on port " + port + "...");
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
} catch(Exception e) {
System.out.println("Error creating server: " + e.getLocalizedMessage());
System.exit(0);
}
System.out.println("Created server port, now waiting for users...");
Socket client = null;
DatagramSocket ds = null;
try {
ds = new DatagramSocket(4);
} catch(Exception e) {
System.out.println("IN:Error creating Datagram Server: " + e.getLocalizedMessage());
e.printStackTrace();
System.exit(0);
}
while (true) {
try {
client = ss.accept();
System.out.println("Connecting user: " + client.getInetAddress().toString());
} catch(Exception e) {
System.out.println("Error on server: " + e.getLocalizedMessage());
}
new MessageConnectionIn(client, ds).start();
new MessageConnectionOut(client, ds).start();
}
}
}
class MessageConnectionOut extends Thread {
protected Socket client;
public DatagramSocket ds;
public MessageConnectionOut(Socket client, DatagramSocket ds) {
this.client = client;
this.ds = ds;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":OUT");
try {
System.out.println("OUT:User connected.");
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
while (true) {
byte[] outgoing = new byte[4096];
DatagramPacket dp = new DatagramPacket(outgoing, outgoing.length);
ds.receive(dp);
dos.writeChars(new String(outgoing) + "\n");
}
} catch(Exception e) {
System.out.println("OUT:Error connecting " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
class MessageConnectionIn extends Thread {
protected Socket client;
public DatagramSocket ds;
public MessageConnectionIn(Socket client, DatagramSocket ds) {
this.client = client;
this.ds = ds;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":IN");
try {
System.out.println("IN:User connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (true) {
String lineIn = br.readLine();
byte[] input = lineIn.getBytes();
System.out.println(lineIn);
byte[] output = new byte[4096];
for (int c = 0; c < output.length; c++) output[c] = 0x0;
for (int i = 0; i < input.length && i < output.length; i++) output[i] = input[i];
DatagramPacket dp = new DatagramPacket(output, output.length, InetAddress.getLocalHost(), 4);
ds.send(dp);
}
} catch(Exception e) {
System.out.println("IN:Error connecting to " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
UPDATE:
I tried replacing all the DatagramSockets with MulticastSockets and adding it to a group when I declared it, MessageServer.main(). The same problem occurred.
Multicast code:
public class MessageServer {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
MessageServer msgsrv = new MessageServer();
System.out.println("Starting server on port " + port + "...");
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
} catch(Exception e) {
System.out.println("Error creating server: " + e.getLocalizedMessage());
System.exit(0);
}
System.out.println("Created server port, now waiting for users...");
Socket client = null;
MulticastSocket ms = null;
try {
ms = new MulticastSocket(4);
ms.joinGroup(InetAddress.getByName("225.65.65.65"));
} catch(Exception e) {
System.out.println("IN:Error creating Datagram Server: " + e.getLocalizedMessage());
e.printStackTrace();
System.exit(0);
}
while (true) {
try {
client = ss.accept();
System.out.println("Connecting user: " + client.getInetAddress().toString());
} catch(Exception e) {
System.out.println("Error on server: " + e.getLocalizedMessage());
}
new MessageConnectionIn(client, ms).start();
new MessageConnectionOut(client, ms).start();
}
}
}
class MessageConnectionOut extends Thread {
protected Socket client;
public MulticastSocket ms;
public MessageConnectionOut(Socket client, MulticastSocket ms) {
this.client = client;
this.ms = ms;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":OUT");
try {
System.out.println("OUT:User connected.");
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
while (true) {
byte[] outgoing = new byte[4096];
DatagramPacket dp = new DatagramPacket(outgoing, outgoing.length);
ms.receive(dp);
dos.writeChars(new String(outgoing) + "\n");
System.out.println("SENT_TO:" + this.getName());
}
} catch(Exception e) {
System.out.println("OUT:Error connecting " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
class MessageConnectionIn extends Thread {
protected Socket client;
public MulticastSocket ms;
public MessageConnectionIn(Socket client, MulticastSocket ms) {
this.client = client;
this.ms = ms;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":IN");
try {
System.out.println("IN:User connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (true) {
String lineIn = br.readLine();
byte[] input = lineIn.getBytes();
System.out.println(lineIn);
byte[] output = new byte[4096];
for (int c = 0; c < output.length; c++) output[c] = 0x0;
for (int i = 0; i < input.length && i < output.length; i++) output[i] = input[i];
DatagramPacket dp = new DatagramPacket(output, output.length, InetAddress.getLocalHost(), 4);
ms.send(dp);
}
} catch(Exception e) {
System.out.println("IN:Error connecting to " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
This sample may be help you out.
There is 2 threads for Server.
One for reading UDP messages. I used 2 different ports since I just want to avoid messages read by same process. I don't have 2 machines to test it. Tested on my local host.
Another thread will broadcast UDP messages received by reader thread.
There is a thread safe list which acts between threads as data sync. Received data added to the list. Broadcaster thread polling the list for the data, if there is any broadcast and else sleep for 500 microseconds. Threads are created using executor.
private final static String INET_ADDR = "224.0.0.3";
private final static int PORT1 = 8888;
private final static int PORT2 = 8889;
private static List<String> threadSafeList = null;
public static void main(String[] args) throws UnknownHostException, InterruptedException {
threadSafeList = new CopyOnWriteArrayList<String>();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Sender(InetAddress.getByName(INET_ADDR), PORT1));
executorService.submit(new Receiver(InetAddress.getByName(INET_ADDR), PORT2));
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
public Receiver (InetAddress inetAddress, int port) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver " + this.port);
byte[] buf = new byte[256];
try {
MulticastSocket clientSocket = new MulticastSocket(this.port);
//Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf, buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
threadSafeList.add(msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
public Sender (InetAddress inetAddress, int port) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Sender Address " + new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
// Open a new DatagramSocket, which will be used to send the data.
while (true) {
try (DatagramSocket serverSocket = new DatagramSocket()) {
for (Iterator<String> it = threadSafeList.iterator(); !threadSafeList.isEmpty() && it.hasNext(); ) {
String i = it.next();
String msg = "Sent message no " + i;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(), msg.getBytes().length, this.addr, this.port);
serverSocket.send(msgPacket);
threadSafeList.remove(i);
System.out.println("Server sent packet with msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
try {
System.out.println("going for sleep");
Thread.currentThread().sleep(500);
System.out.println("going for sleeping");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Design can be modified by changing the creation of sender thread. Whenever receiver thread gets a message, create a sender thread and do the broadcast and shutdown that thread. You can use reusable thread pool instead of fixed Thread pool what used in this example. And you can pass message as argument while you create sender thread (so list may not be needed at all) and do the submit. I do have code.
public static void main(String[] args) throws UnknownHostException,
InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new Receiver(InetAddress.getByName(INET_ADDR),
PORT2, executorService));
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
And inner classes,
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
private ExecutorService executorService;
public Receiver(InetAddress inetAddress, int port,
ExecutorService executorService) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
this.executorService = executorService;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver " + this.port);
byte[] buf = new byte[256];
try {
MulticastSocket clientSocket = new MulticastSocket(this.port);
// Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf,
buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
executorService.submit(new Sender(InetAddress
.getByName(INET_ADDR), PORT1, msg));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
And
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
private String message;
public Sender(InetAddress inetAddress, int port, String message)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
this.message = message;
}
public void run() {
System.out.println(" # Sender Address "
+ new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
try {
DatagramSocket serverSocket = new DatagramSocket();
String msg = "Sent message no " + message;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(),
msg.getBytes().length, this.addr, this.port);
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Client has got 2 threads,
One for reading broadcaster messages.
Another for sending 5 messages in loop. Once it is finished, thread will shut-down.
No data exchange here, so no thread safe list.
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
public Receiver(InetAddress inetAddress, int port)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver port " + this.port);
byte[] buf = new byte[256];
try (MulticastSocket clientSocket = new MulticastSocket(this.port)) {
// Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf,
buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
And
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
public Sender(InetAddress inetAddress, int port)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Sender Address "
+ new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
// Open a new DatagramSocket, which will be used to send the data.
try {
DatagramSocket serverSocket = new DatagramSocket();
for (int i = 0; i < 5; i++) {
System.out.println("inside loop");
String msg = "Sent message no 2" + i;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(
msg.getBytes(), msg.getBytes().length, this.addr,
this.port);
System.out.println("Before sending to socket");
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
This article sample code is extended further.
Code to be fine tuned.

UDP Unicast Communication between three servers using java

I want to make three servers communicate using java UDP. If a particular method which exists for all the three servers is called on the first server instance the other two servers should also communicate the result for those methods to the first servers using UDP. Should I be using multicast ? I tried using Unicast but its not working out.
UDPDataExchangeclass
import java.io.BufferedReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
public class UDPDataExchange {
String Hostname;
static InetAddress IPAddress;
UDPDataExchange() {
Hostname = new String("127.0.0.1");
try {
IPAddress = InetAddress.getByName(Hostname);
}
catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void requestData(int portNumber, String data) {
try {
DatagramSocket clientSocket = new DatagramSocket();
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
byte[] sendData = new byte[1024];
sendData = data.getBytes();
System.out.print("Ready to send data ");
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, IPAddress, portNumber);
clientSocket.send(sendPacket);
clientSocket.setSoTimeout(10000);
try {
clientSocket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
InetAddress returnIPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
System.out.println("From server at: " + returnIPAddress + ":"
+ port);
System.out.println("Message: " + modifiedSentence);
}
catch (SocketTimeoutException ste) {
System.out.println("Timeout Occurred: Packet assumed lost");
}
//clientSocket.close();
}
catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void responseData(int portNumber) {
try {
DatagramSocket serverSocket = new DatagramSocket(portNumber);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while (true) {
receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
System.out.println("Waiting for datagram packet");
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
System.out.println("From: " + IPAddress + ":" + port);
System.out.println("Message: " + sentence);
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
}
}
catch (SocketException ex) {
System.out.println("UDP Port 9876 is occupied.");
System.exit(1);
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
UDPTest
import java.io.*;
import java.net.*;
class UDPTest extends UDPDataExchange {
public static void main(String args[]) throws Exception {
int UDPClientConcordiaPortNumber = 9876;
int UDPClientMcgillPortNumber=9890;
int UDPClientDawsonPortNumber=9891;
UDPTest McgillServer=new UDPTest();
UDPTest DawsonServer=new UDPTest();
McgillServer.responseData(UDPClientConcordiaPortNumber);
DawsonServer.responseData(UDPClientDawsonPortNumber);
UDPTest concordiaTest = new UDPTest();
System.out.println("Attemping to connect to " + IPAddress
+ ") via UDP port" + UDPClientConcordiaPortNumber);
String concordiaData = "Hello from concordia";
System.out.println("Sending data " + concordiaData.length()
+ " bytes to server.");
concordiaTest.requestData(UDPClientConcordiaPortNumber, concordiaData);
}
}
In the UDPDataExchange I've defined two methods to send and receive data. In the UDPTest class I am trying to create two server instances namely mcgill and dawson server who would listen to concordia's port for data sent. Once they receive it they send a response back to Concordia
Try this, I´m not sure if it is exactly what you want.
UDPDataExchange
public class UDPDataExchange {
String Hostname;
static InetAddress IPAddress;
UDPDataExchange() {
Hostname = new String("127.0.0.1");
try {
IPAddress = InetAddress.getLocalHost();
} catch (final UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void requestData(final int portNumber, final String data) {
try {
final DatagramSocket clientSocket = new DatagramSocket();
final byte[] receiveData = new byte[1024];
final DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
byte[] sendData = new byte[1024];
sendData = data.getBytes();
System.out.print("Ready to send data ");
final DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, IPAddress, portNumber);
clientSocket.send(sendPacket);
clientSocket.setSoTimeout(10000);
try {
clientSocket.receive(receivePacket);
final String modifiedSentence = new String(receivePacket.getData());
final InetAddress returnIPAddress = receivePacket.getAddress();
final int port = receivePacket.getPort();
System.out.println("From server at: " + returnIPAddress + ":"
+ port);
System.out.println("Message: " + modifiedSentence);
} catch (final SocketTimeoutException ste) {
System.out.println("Timeout Occurred: Packet assumed lost");
}
// clientSocket.close();
} catch (final SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void responseData(final int portNumber) {
try {
final DatagramSocket serverSocket = new DatagramSocket(portNumber, IPAddress);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while (true) {
receiveData = new byte[1024];
final DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
System.out.println("Waiting for datagram packet");
serverSocket.receive(receivePacket);
final String sentence = new String(receivePacket.getData());
final InetAddress IPAddress = receivePacket.getAddress();
final int port = receivePacket.getPort();
System.out.println("From: " + IPAddress + ":" + port);
System.out.println("Message: " + sentence);
final String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
final DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
}
} catch (final SocketException ex) {
System.out.println("UDP Port 9876 is occupied.");
System.exit(1);
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
UDPTest
class UDPTest extends UDPDataExchange {
public static void main(final String args[]) throws Exception {
final int UDPClientConcordiaPortNumber = 9876;
final int UDPClientMcgillPortNumber = 9890;
final int UDPClientDawsonPortNumber = 9891;
final UDPTest McgillServer = new UDPTest();
final UDPTest DawsonServer = new UDPTest();
final Thread t1 = new Thread() {
#Override
public void run() {
McgillServer.responseData(UDPClientMcgillPortNumber);
}
};
t1.setDaemon(true);
t1.start();
final Thread t2 = new Thread() {
#Override
public void run() {
DawsonServer.responseData(UDPClientDawsonPortNumber);
}
};
t2.setDaemon(true);
t2.start();
final UDPTest concordiaTest = new UDPTest();
System.out.println("Attemping to connect to " + IPAddress
+ ") via UDP port" + UDPClientConcordiaPortNumber);
final String concordiaData = "Hello from concordia";
System.out.println("Sending data " + concordiaData.length()
+ " bytes to server.");
concordiaTest.requestData(UDPClientMcgillPortNumber, concordiaData);
concordiaTest.requestData(UDPClientDawsonPortNumber, concordiaData);
}
}
I´ll explain brielfy what I changed:
UDPDataExchange:
I changed the IPAdress to InetAddress.getLocalHost()
UDPTest:
Each call to responseData runs in a separate Thread, to avoid blocking the main thread.
That threads are daemon to allow exit application.
The requestData() invocation has changed to call each server.
Hope to be useful.

UDP socket chat application in java

I'm trying to create a very simple chat application in Java using UDP sockets. There is one server and multiple clients.
right now my code is :
Server :
package chat;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Set;
class User{
InetAddress addr;
int port;
User(InetAddress a,int p){
addr = a;
port = p;
}
}
public class Server {
private static final int PORT = 27012;
private static DatagramSocket sckt;
private static DatagramPacket in,out;
private static byte[] buffer;
private static HashMap<String,User> users;
public static void main(String[] args) {
try{
System.out.println("Opening port...");
sckt = new DatagramSocket(PORT);
users = new HashMap<String,User>();
}
catch(SocketException e){
System.out.println("Port connection failed!");
System.exit(1);
}
handleClient();
}
private static void sendMsg(InetAddress addr, int port, String msg){
try{
out = new DatagramPacket(msg.getBytes(),msg.length(),addr,port);
sckt.send(out);
}catch(IOException e){
e.printStackTrace();
}
}
private static void handleClient(){
try{
String msgIn,msgOut="",senderNick;
do{
buffer = new byte[256];
in = new DatagramPacket(buffer,buffer.length);
sckt.receive(in);
InetAddress clientAddress = in.getAddress();
int clientPort = in.getPort();
msgIn = new String(in.getData(),0,in.getLength());
//print msgIn
//System.out.println(msgIn);
senderNick = msgIn.substring(0,msgIn.indexOf(" "));
msgIn = msgIn.substring(msgIn.indexOf(" ")+1);
if(msgIn.equals("/connect")){
//String nick = msgIn.substring(msgIn.indexOf(" ") + 1);
System.out.println(senderNick);
if(users.containsKey(senderNick)){
msgOut = "Nick already in use!";
}
else{
users.put(senderNick, new User(clientAddress,clientPort));
msgOut = "Connected!";
}
sendMsg(clientAddress,clientPort,msgOut);
}
else if(msgIn.equals("/list")){
Set userNames;
userNames = users.keySet();
msgOut = "Users : \n";
msgOut += userNames.toString();
sendMsg(clientAddress,clientPort,msgOut);
}
else if(msgIn.startsWith("/msg")){
String tmp = msgIn.substring(msgIn.indexOf(" ")+1);
String receiverName = tmp.substring(0,tmp.indexOf(" "));
String message = tmp.substring(tmp.indexOf(" ")+1);
if(!users.containsKey(receiverName)){
msgOut = "User " + receiverName + " not found!";
sendMsg(clientAddress,clientPort,msgOut);
}
else{
User receiver = users.get(receiverName);
msgOut = "Message from "+ senderNick +" : "+message;
sendMsg(clientAddress,clientPort,"Message Sent!");
sendMsg(receiver.addr,receiver.port,msgOut);
}
}
else if(msgIn.startsWith("/nick")){
String newNick = msgIn.substring(msgIn.indexOf(" ")+1);
if(users.containsKey(newNick)){
msgOut = "Nick already in use!";
}
else{
users.put(newNick,users.get(senderNick));
users.remove(senderNick);
msgOut = "Nick changed!";
}
sendMsg(clientAddress,clientPort,msgOut);
}
else if(msgIn.equals("/disconnect")){
users.remove(senderNick);
}
//out = new DatagramPacket(msgOut.getBytes(),msgOut.length(),clientAddress,clientPort);
//sckt.send(out);
}while(true);
}
catch(IOException e){
e.printStackTrace();
}
finally{
System.out.println("Closing connection.");
sckt.close();
}
}
}
Client :
package chat;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
private static InetAddress host;
private static final int PORT = 27012;
private static DatagramSocket sckt;
private static DatagramPacket in, out;
private static byte[] buffer;
private static String nick;
static class MessageListener implements Runnable {
//DatagramPacket in;
//byte[] buffer;
String reply;
public void run() {
do{
try{
buffer = new byte[256];
in = new DatagramPacket(buffer,buffer.length);
sckt.receive(in);
reply = new String(in.getData(),0,in.getLength());
System.out.println("SERVER> "+reply);
}
catch(IOException e){
e.printStackTrace();
}
}while(true);
}
}
public static void main(String[] args) {
try {
host = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
System.out.println("Host not found!");
System.exit(1);
}
connect();
}
private static void sendMsg(String msg) {
try {
out = new DatagramPacket(msg.getBytes(), msg.length(), host, PORT);
sckt.send(out);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void connect() {
Scanner sc = new Scanner(System.in);
try {
buffer = new byte[256];
sckt = new DatagramSocket();
String reply = "";
do {
System.out.println("Name: ");
nick = sc.nextLine();
sendMsg(nick + " /connect");
in = new DatagramPacket(buffer, buffer.length);
sckt.receive(in);
reply = new String(in.getData(), 0, in.getLength());
System.out.println("SERVER> " + reply);
} while (!reply.equals("Connected!"));
accessServer();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void accessServer() {
try {
sckt = new DatagramSocket();
Scanner sc = new Scanner(System.in);
String msg = "", reply = "";
Thread myT = new Thread(new MessageListener());
myT.start();
do {
System.out.print("Enter Message: ");
msg = sc.nextLine();
if (!msg.equals("/quit")) {
buffer = new byte[256];
sendMsg(nick + " " + msg);
} else {
sendMsg(nick + " /disconnect");
}
} while (!msg.equals("/quit"));
sc.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Connection closing...");
sckt.close();
}
}
}
I want to be able to send a message to a single user or to all the users but the problem is that i can't receive the message on the client because as it stands now the client only receives a message after it sends one to the server. So my thought was to use a thread that continuosly listens for messages from the server but it doesn't work. What's the easiest way to go about this ?
You are attempting to use the received datagram immediately, instead of waiting for the thread you created to receive a datagram and populate your in variable. You could either handle the received datagram directly in the thread's code, or signal the main thread when a datagram is received using a wait() / notify() scheme.

Categories

Resources