Server-Client in UDP - java

My Datagram simple client server program is giving error.Client takes information from server and server also gets information from client.
Here is my Server:
package udp;
import java.net.*;
public class DatagramServer implements Runnable {
DatagramPacket pack;
DatagramSocket sock;
DatagramServer() {
new Thread(this).start();
}
public void run() {
try {
while (true) {
recieve();
send();
}
} catch (Exception e) {
System.out.println(e);
}
}
public void send() throws Exception {
byte data[] = "This is a \n datagram packet".getBytes();
InetAddress add = InetAddress.getByName("localhost");
pack = new DatagramPacket(data, data.length, add, 8000);
sock = new DatagramSocket();
sock.send(pack);
sock.close();
}
public void recieve() throws Exception {
byte[] buffer = new byte[65536];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
sock = new DatagramSocket(8000);
sock.receive(incoming);
byte[] data = incoming.getData();
String s = new String(data, 0, incoming.getLength());
}
public static void main(String[] args) {
new DatagramServer();
}
}
And here is my Client :
package udp;
import java.net.*;
public class DatagramClient {
DatagramPacket pack;
DatagramSocket sock;
DatagramClient() {
Thread t1 = new Thread() {
public void run() {
while (true) {
try {
receive();
Thread.sleep(5000);
} catch (Exception e) {
System.out.println(e);
}
}
}
};
t1.start();
Thread t2 = new Thread() {
public void run() {
while (true) {
try {
send();
Thread.sleep(5000);
} catch (Exception e) {
System.out.println(e);
}
}
}
};
t2.start();
}
public void receive() throws Exception {
byte data[] = new byte[1000];
pack = new DatagramPacket(data, data.length);
sock = new DatagramSocket(8000);
sock.receive(pack);
System.out.println("Data::" + new String(pack.getData(), "UTF-8"));
System.out.println("Port::" + pack.getPort());
sock.close();
}
public void send() throws Exception {
String s = "KOLI SDF DFEF XFFFSS";
byte[] b = new byte[1000];
b = s.getBytes();
DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress.getByName("localhost"), 8000);
sock= new DatagramSocket(8000);
sock.send(dp);
}
public static void main(String[] args) {
new DatagramClient();
}
}
I'm getting errors like:
java.net.BindException: Address already in use: Cannot bind
java.net.BindException: Address already in use: Cannot bind
java.net.BindException: Address already in use: Cannot bind
java.net.BindException: Address already in use: Cannot bindBUILD STOPPED (total time: 4 seconds)
What should i do?

Your client and server has some issues such as open same port 8000 in different threads so I have fixed those within the following code.
Client
package udp;
import java.net.*;
public class DatagramClient {
DatagramPacket pack;
DatagramSocket sock;
DatagramClient() {
Thread t1 = new Thread() {
public void run() {
while (true) {
try {
receive();
Thread.sleep(5000);
} catch (Exception e) {
System.out.println(e);
}
}
}
};
t1.start();
}
public void receive() throws Exception {
byte data[] = new byte[1000];
pack = new DatagramPacket(data, data.length);
sock = new DatagramSocket(8000);
sock.receive(pack);
System.out.println("Data::" + new String(pack.getData(), "UTF-8"));
System.out.println("Port::" + pack.getPort());
sock.close();
}
public void send() throws Exception {
String s = "KOLI SDF DFEF XFFFSS";
byte[] b = new byte[1000];
b = s.getBytes();
DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress.getByName("localhost"), 8000);
sock= new DatagramSocket(8000);
sock.send(dp);
}
public static void main(String[] args) {
new DatagramClient();
}
}
Server
package udp;
import java.net.*;
public class DatagramServer implements Runnable {
DatagramPacket pack;
DatagramSocket sock;
DatagramServer() {
new Thread(this).start();
}
public void run() {
try {
while (true) {
//recieve();
send();
}
} catch (Exception e) {
System.out.println(e);
}
}
public void send() throws Exception {
byte data[] = "This is a \n datagram packet".getBytes();
InetAddress add = InetAddress.getByName("localhost");
pack = new DatagramPacket(data, data.length, add, 8000);
sock = new DatagramSocket();
sock.send(pack);
sock.close();
}
public void recieve() throws Exception {
byte[] buffer = new byte[65536];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
sock = new DatagramSocket(8000);
sock.receive(incoming);
byte[] data = incoming.getData();
String s = new String(data, 0, incoming.getLength());
}
public static void main(String[] args) {
new DatagramServer();
}
}

The problem is your server code is trying to bind to the 8000 port each time receive () called. And receive is being called repeatedly from within the while(true) loop. So it tries to bind to the same port again and again.
To fix it remove the UDP socket instantiation i.e
sock = new DatagramSocket(8000);
From the receive method and put it before your while loop begins.

Related

How to send messages between two 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'm not sure how to make them communicate in groups of 2 like in a peer-to-peer connection.
class Server {
private static DatagramSocket socket = null;
private static Map<Session, Integer> sessions = new HashMap<Session, Integer>();
private static Session session = new Session();
public static void main(String[] args) {
try {
socket = new DatagramSocket(6066);
} catch (SocketException e) {
System.out.println("[SERVER] Unable to launch server on port: " + socket.getLocalPort());
}
System.out.println("[SERVER] Server launched successfully on port " + socket.getLocalPort());
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
byte[] buffer = new byte[100];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
Arrays.fill(buffer, (byte) 0);
try {
socket.receive(packet);
} catch (IOException e) {
System.out.println("[SERVER] Unable to receive packets from buffer");
}
InetAddress ip = packet.getAddress();
int port = packet.getPort();
String data = new String(packet.getData()).trim();
if(session.getIp1() == null) {
session.setIp1(ip);
session.setPort1(port);
session.setData1(data);
} else {
session.setIp2(ip);
session.setPort2(port);
session.setData2(data);
}
DatagramPacket pt = new DatagramPacket(packet.getData(), packet.getData().length, ip, port);
try {
socket.send(pt);
} catch (IOException e) {
System.out.println("[SERVER] Unable to send packets to client.");
}
}
}
});
thread.start();
}
}
Client:
public class Client {
private static DatagramSocket socket = null;
public static void main(String[] args) {
System.out.println("Send to server:");
Scanner scanner = new Scanner(System.in);
while (true) {
try {
// port shoudn't be the same as in TCP but the port in the datagram packet must
// be the same!
socket = new DatagramSocket();
} catch (SocketException e1) {
System.out.println("[CLIENT] Unable to initiate DatagramSocket");
}
InetAddress ip = null;
try {
ip = InetAddress.getByName("127.0.0.1");
} catch (UnknownHostException e) {
System.out.println("[CLIENT] Unable to determine server IP");
}
// must be in a while loop so we can continuously send messages to server
String message = null;
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
receive();
}
});
thread.start();
while (scanner.hasNextLine()) {
message = scanner.nextLine();
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ip, 6066);
try {
socket.send(packet);
} catch (IOException e) {
System.out.println("[CLIENT] Unable to send packet to server");
}
}
}
}
private static void receive() {
// receiving from server
byte[] buffer2 = new byte[100];
DatagramPacket ps = new DatagramPacket(buffer2, buffer2.length);
while (true) {
try {
socket.receive(ps);
} catch (IOException e) {
System.out.println("[CLIENT] Unable to receive packets from server.");
}
System.out.println("[SERVER] " + new String(ps.getData()));
}
}
}
Object class:
public class Session {
private InetAddress ip1;
private int port1;
private String data1;
private InetAddress ip2;
private int port2;
private String data2;
public Session() {
}
public InetAddress getIp1() {
return ip1;
}
public void setIp1(InetAddress ip1) {
this.ip1 = ip1;
}
public int getPort1() {
return port1;
}
public void setPort1(int port1) {
this.port1 = port1;
}
public String getData1() {
return data1;
}
public void setData1(String data1) {
this.data1 = data1;
}
public InetAddress getIp2() {
return ip2;
}
public void setIp2(InetAddress ip2) {
this.ip2 = ip2;
}
public int getPort2() {
return port2;
}
public void setPort2(int port2) {
this.port2 = port2;
}
public String getData2() {
return data2;
}
public void setData2(String data2) {
this.data2 = data2;
}
}
Currently, you store the client's information in an array. Make an object where it will contain two client session's data. When a new client is attempting to connect, see if there are any objects that have a free spot, if not, create a new object and await a new participant; otherwise, join an existing session.
Hackish way: Create a Map<ObjectHere, UserCount> then filter based on userCounts = 1 and then join the session to the first returned Object.

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. ;-)

java Peer to Peer using UDP socket

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

Communication between Java programs with DatagramSocket

I'm trying to communicate two java programs, no problem with this. Program A send a message with the word "token" and Program B receive the message and print it. The problem I have is I would like to send before length of message to Program B to create the array with the accurate length but i don't know how can i do it.
public class ProgramA {
public static void main(String[] args) {
try {
DatagramSocket datagramSocket = new DatagramSocket();
String message = "token";
InetAddress addr = InetAddress.getByName("localhost");
DatagramPacket datagram = new DatagramPacket(message.getBytes(),message.getBytes().length, addr, 5556);
datagramSocket.send(datagram);
datagramSocket.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public class ProgramB {
public static void main(String[] args) {
try {
InetSocketAddress addr = new InetSocketAddress("localhost", 5556);
DatagramSocket datagramSocket = new DatagramSocket(addr);
byte[] message = new byte[5];
DatagramPacket datagram = new DatagramPacket(message, message.length);
datagramSocket.receive(datagram);
datagramSocket.close();
for(int i = 0; i < message.length; i++) {
System.out.print((char)message[i]);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
If you know that the length of the message is maximum X bytes, you could use something like this:
package experiment;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ProgramA {
public static void main(String[] args) {
try {
System.out.println("Started");
DatagramSocket datagramSocket = new DatagramSocket();
String message = "tokenasdfasdfasdfasdf";
InetAddress addr = InetAddress.getByName("localhost");
DatagramPacket datagramLength = new DatagramPacket(new byte[]{(byte)message.length()}, 1, addr, 5556);
DatagramPacket datagram = new DatagramPacket(message.getBytes(),message.getBytes().length, addr, 5556);
datagramSocket.send(datagramLength);
datagramSocket.send(datagram);
datagramSocket.close();
System.out.println("Done");
}
catch (IOException e) {
e.printStackTrace();
}
}
}
package experiment;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class ProgramB {
public static void main(String[] args) {
try {
InetSocketAddress addr = new InetSocketAddress("localhost", 5556);
DatagramSocket datagramSocket = new DatagramSocket(addr);
byte[] messageLength = new byte[1];
DatagramPacket datagramLength = new DatagramPacket(messageLength, 1);
datagramSocket.receive(datagramLength);
byte[] message = new byte[(int)messageLength[0]];
DatagramPacket datagram = new DatagramPacket(message, message.length);
datagramSocket.receive(datagram);
datagramSocket.close();
for(int i = 0; i < message.length; i++) {
System.out.print((char)message[i]);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
This works assumed the length of the message does not exceed 127; otherwise your datagramPacket with the lenght of the message has to contain more than one byte

Multithreading Java Socket

I have been asked to take this post down, and in particular the code, by a superior of mine
Problem 1: Client did not receive message
Solution: Make sure port matches sending's port
Problem 2: Could not broadcast message
Solution: Use a broadcast address
// Client REceive
DatagramSocket socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress("127.0.0.1", 4002));
// ClientSEnd
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
socket = new DatagramSocket();
socket.setReuseAddress(true);
Just add the port number to the Datagram socket in the receive. it will work fine.
Class - ClientReceive:
DatagramSocket socket = new DatagramSocket(4001);
Set the reuse address to true ..
that will make use of the address whatever it is 4001 4002..etc
socket.setReuseAddress(true);
The problem seems to be that DatagramSocket allows you to send a datagram to a given destination. In your case you are sending to localhost, so that all messages are sent to the local machine only and not to other clients. If you want to reach all network clients should use a broadcast address or use the MulticastSocket class instead DatagramSocket.
import java.net.*;
import java.io.*;
public class ClientSend implements Runnable
{
private Thread t;
private DatagramSocket socket;
private String name;
private String sendingMessage;
private int port;
public ClientSend(int port)
{
this.port = port;
}
public void run()
{
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
socket = new DatagramSocket();
socket.setReuseAddress(true);
while(true)
{
sendingMessage = br.readLine();
byte sendingData[] = sendingMessage.getBytes();
InetAddress clientAddress = InetAddress.getByName("224.0.0.3");
DatagramPacket sendingPacket = new DatagramPacket(sendingData, sendingData.length, clientAddress, 4011);
socket.send(sendingPacket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void start()
{
t = new Thread(this);
t.start();
}
public static void main(String args[]) throws Exception
{
ClientSend CS = new ClientSend(4011);
CS.start();
}
}
import java.net.;
import java.io.;
public class ClientReceive implements Runnable
{
private Thread t;
public ClientReceive()
{
}
public void run()
{
try {
// DatagramSocket socket = new DatagramSocket(null);
MulticastSocket socket = new MulticastSocket(4011);
InetAddress group = InetAddress.getByName("10.10.222.120");
socket.joinGroup(group);
//socket.setReuseAddress(true);
//socket.bind(new InetSocketAddress("10.10.222.120", 4011));
while(true)
{
byte receivingData[] = new byte[1024];
DatagramPacket receivingPacket = new DatagramPacket(receivingData, receivingData.length);
socket.receive(receivingPacket);
String receivingMessage = new String(receivingPacket.getData(), 0, receivingPacket.getLength());
System.out.println("Received: " + receivingMessage);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void start()
{
t = new Thread(this);
t.start();
}
public static void main(String args[]) throws Exception
{
ClientReceive CR = new ClientReceive();
CR.start();
}
}

Categories