I have a program wHich puts the inetAddress and port for each client connected to the UDP server in a hashmap. The reason for this is so i can take messages from clients send them to the server and send them over to some other clients inside the hashmap.
However when i do this it only puts it only once inside the hashmap. How could i make it so for every new client it would add a HashMap<InetAdress, Integer> for every new client connection?
server:
private static int port = 9001;
private static HashMap<InetAddress, Integer> clients = new HashMap<InetAddress, Integer>();
public static void main(String[] args) throws Exception {
DatagramSocket UDPSocket = new DatagramSocket(9002);
System.out.println("[SERVER] UDP Server successfully launched on port: " + port);
byte[] data = new byte[1000];
DatagramPacket receivePacket = new DatagramPacket(data, data.length);
while (true) {
UDPSocket.receive(receivePacket);
while(true) {
InetAddress ip = receivePacket.getAddress();
int port = receivePacket.getPort();
clients.put(ip, port);
}
}
}
client:
public ChatClient() throws UnknownHostException, IOException {
Scanner scanner = new Scanner(System.in);
DatagramSocket UDPSocket = new DatagramSocket();
while(scanner.hasNextLine()) {
String message = scanner.nextLine();
InetAddress ip = InetAddress.getByName("127.0.0.1");
DatagramPacket packet = new DatagramPacket(message.getBytes(), message.getBytes().length, ip, 9002);
UDPSocket.send(packet);
}
}
Related
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. ;-)
I am making a peer to peer chat application for which I have written the below code for chat with one person. This code works for localhost(127.0.0.1) but doesn't work for any specific ip address(192.168.43.118) and throws bindexception. Please help.
import java.sql.*;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class communicate {
public static void main(String args[]) throws Exception {
communicate ob = new communicate();
String ip = "192.168.43.118";
ob.text(ip);
}
public void text(String friend_ip) throws Exception{
System.out.println("Press 'Exit' to exit the chat");
int send_port = 40002;
int receive_port = 40002;
//InetAddress inetaddr = InetAddress.getByName(friend_ip);
byte[] ipAddr = new byte[] { (byte)192, (byte)168, (byte)43, (byte)118 };
System.out.println(ipAddr.length);
InetAddress inetaddr = InetAddress.getByAddress(ipAddr);
System.out.println("B");
DatagramSocket serverSocket = new DatagramSocket(receive_port, inetaddr);
System.out.println("YO");
Runnable send = new SendMsg(send_port, friend_ip, serverSocket);
Runnable receive = new GetMsg(friend_ip, receive_port, serverSocket);
Thread t1 = new Thread(send);
Thread t2 = new Thread(receive);
t1.start();
t2.start();
}
class SendMsg implements Runnable {
private DatagramSocket senderSocket;
private int send_port;
private String sendto_ip;
SendMsg(int port, String friend_ip, DatagramSocket ds)throws Exception {
senderSocket = new DatagramSocket(64432);
send_port = port;
sendto_ip = friend_ip;
}
public void run(){
try {
while(true) {
String sendString;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
sendString = br.readLine();
byte[] sendData = sendString.getBytes();
byte[] ipAddr = new byte[] { (byte)192, (byte)168, (byte)43, (byte)118 };
InetAddress inetAddress = InetAddress.getByAddress(ipAddr);
DatagramPacket sendPacket = new DatagramPacket (sendData, sendData.length, inetAddress, send_port);
senderSocket.send(sendPacket);
System.out.println("Message Sent");
}
}
catch(Exception e) {
System.out.println("Exc at Sender\n" + e);
}
finally {
if(senderSocket != null) senderSocket.close();
}
}
}
class GetMsg implements Runnable{
private DatagramSocket serverSocket;
private String friend_ip;
private int receive_port;
GetMsg(String ip, int port, DatagramSocket ds) throws Exception{
friend_ip = ip;
receive_port = port;
serverSocket = ds;
}
public void run(){
try {
while(true) {
byte[] receiveData = new byte[10000];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String message = new String (receivePacket.getData(), 0, receivePacket.getLength());
System.out.println(friend_ip + ": " + message);
}
}
catch(Exception e) {
System.out.println("Exc at Rec\n" + e);
}
finally {
if(serverSocket != null) serverSocket.close();
}
}
}
}
When I run it on terminal the following output is shown
Press 'Exit' to exit the chat
4
B
Exception in thread "main" java.net.BindException: Cannot assign requested address (Bind failed)
at java.base/java.net.PlainDatagramSocketImpl.bind0(Native Method)
at java.base/java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:131)
at java.base/java.net.DatagramSocket.bind(DatagramSocket.java:394)
at java.base/java.net.DatagramSocket.<init>(DatagramSocket.java:244)
at java.base/java.net.DatagramSocket.<init>(DatagramSocket.java:301)
at communicate.text(communicate.java:21)
at communicate.main(communicate.java:10)
As "YO" is not printed it seems that error is in the text method where I am trying to create DatagramSocket. Where am I going wrong?
If you want read, do not bind the remote address. Just create a local UDP socket (it will be a server socket) and just read from/write to its buffer. You can bind to your local network interface only and these must be initialized before. So you cannot bind to an unused Wifi, or unplugged ethernet adapter.
If you want test a sender, and a receiver in the same java program on different threads, you have to use two different socket.
A hint: use InetAddress.getByName(IPv4) for string IP input, you do not need the byte array.
I've created this SpringBoot app, exploring networking communication with Java, over the User Datagram Protocol. I am running the the application in Eclipse Java EE IDE for Web Developers, Version: Oxygen.1a Release (4.7.1a)
Here the main class:
#Override
public void run(String... args) throws Exception {
socket = new DatagramSocket(UDP_PORT);
byte[] receiveData = new byte[BUFFER_SIZE];
byte[] sendData = new byte[BUFFER_SIZE];
LOG.info("UDP server init...");
while (true) {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket.receive(receivePacket);
String sentence = new String( receivePacket.getData(), 0, receivePacket.getLength() );
LOG.info("recived [" + sentence + "] from " + receivePacket.getAddress());
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
DatagramPacket sendPacket = new DatagramPacket(receiveData, receiveData.length, IPAddress, receivePacket.getPort());
socket.send (sendPacket);
}
}
Here a client UDP class I've created to test the Server
public class UDPClient {
private final static int TCP_PORT = 5202;
private DatagramSocket socket;
private InetAddress address;
private byte[] buf;
public UDPClient() throws SocketException, UnknownHostException {
socket = new DatagramSocket();
address = InetAddress.getByName("localhost");
}
public String sendEcho(String msg) throws IOException {
buf = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, TCP_PORT);
socket.send(packet);
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
return received;
}
public void close() {
socket.close();
}
public static void main(String[] args) throws IOException, InterruptedException {
UDPClient udpClient = new UDPClient();
for (;;) {
TimeUnit.SECONDS.sleep(3);
System.out.println
(udpClient.sendEcho("cullons"));
}
}
}
in my computer is working fine, then I deploy the UDPServer on a server, I got the ip using ipconfig
IPv4 Address. . . . . . . . . . . : 214.146.86.201
Then I replace "localhost" for "214.146.86.201", but I don't receive any message in the server.
I've done nc -vzu 214.146.86.201 5202 from my computer
with the result:
MacBook-Pro-de-lopes:$ nc -vzu 214.146.86.201 5202
found 0 associations
found 1 connections:
1: flags=82<CONNECTED,PREFERRED>
outif (null)
src 192.166.26.140 port 56827
dst 214.146.86.201 port 5202
rank info not available
Connection to 214.146.86.201 port 5202 [udp/*] succeeded!
But the server prints null on LOG.info("socket InetAddres: " + socket.getInetAddress()); and LOG.info("socket RemoteSocketAddress: " + socket.getRemoteSocketAddress());
I also tried in the server socket = new DatagramSocket(UDP_PORT, InetAddress.getByName("214.146.86.201")); with the same result
The most probable problem could be that the 5202 port on your server is not accessible from the client. The port and their accessibility may not be the same as TCP but anyway there is always the possibility that someone in between is dropping your data packets.
The simplest workaround is to try to run both your client and server code on the server (214.146.86.201). If it can connect means there is definitely a communication issue which (seems) you can check using Netcat as described here. I didn't try it myself.
I have an UDP send and receive which works in my device Samsung Galaxy Ace Plus (S7500) but the same code doesn't work in other devices, for example Samsung Galaxy S4. I don't have any error.
Send :
public class SendThread extends Thread {
byte[] receiveData = new byte[1024];
DatagramSocket serverSocket = null;
public SendThread() {
this.start();
}
public void run() {
DatagramSocket serverSocket = null;
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
try {
serverSocket = new DatagramSocket("MY SOCKET PORT");
InetAddress IP = InetAddress.getByName("MY IP");
String send= "I am Android";
sendData = send.getBytes();
DatagramPacket send = new DatagramPacket(sendData, sendData.length, IP, "MY SEND PORT");
serverSocket.send(send);
serverSocket.close();
} catch (Exception e) {
}
}
}
Receive :
public class ReceiveThread extends Thread {
byte[] receiveData = new byte[1024];
DatagramSocket serverSocket = null;
boolean isActive = true;
public ReceiveThread() {
this.start();
}
public void run() {
DatagramSocket serverSocket = null;
byte[] receiveData = new byte[1024];
while (isActive) {
try {
serverSocket = new DatagramSocket("MY RECEIVE PORT");
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String( receivePacket.getData());
System.out.println("RECEIVED: " + sentence);
serverSocket.close();
} catch (Exception e){
}
}
}
}
This problem ocurred because some devices lock the Datagram receiver because the protocol security implemented by factory.
Your code is not wrong, but you need change the DatagramSocket for MulticastSocket.
For this your need execute some steps:
First, it's needed to add the uses-permission:
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
On AmdroidManifest.xml
Second, it's necessary create a MulticastLock; Without this the MulticastSocket is not work properly;
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
multicastLock = wifi.createMulticastLock("multicastLock");
multicastLock.setReferenceCounted(true);
Thirdy, replace the DatagramSocket by MulticastSocket. Only on receive methods was needed put the code below or similar:
MulticastSocket ms = new MulticastScoket("Your socket port");
ms.joinGroup("Your IP");
It's not needed any modifies to send messages.
I use the multcast ip equals to 239.255.255.255. Attempt to range of multicast ip because the wrong ip will block the method flow correctly.
Finally, before use MulticastSocket it's needed to execute MulticastLock.acquire(), and after use execute MulticastLock.release();
It could be puted on service, and acquire or release MulticastLock on start or stop service.
Is it possible to use a single DatagramSocket to send and receive packets in a single Java application? I have been attempting to do this using threads but have had not luck. Every socket tutorial I find online uses separate client and server classes to send data. However, in my case, I want the client and server to reside in a single application. Below is my attempt:
public class Main implements Runnable {
// global variables
static DatagramSocket sock;
String globalAddress = "148.61.112.104";
int portNumber = 9876;
byte[] receiveData = new byte[1024];
public static void main(String[] args) throws IOException {
sock = new DatagramSocket();
(new Thread(new Main())).start();
// send data
while (true) {
InetAddress IPAddress = InetAddress.getByName("127.0.0.1");
int port = 9876;
int length = 1024;
byte [] sendData = new byte[1024];
String message = "hello";
sendData = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
IPAddress, port);
sock.send(sendPacket);
}
}
public void run() {
//get incoming data
while (true) {
byte[] sendData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
receivePacket.setPort(portNumber);
try {
sock.receive(receivePacket);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String sentence = new String(receivePacket.getData());
System.out.println("RECEIVED: " + sentence);
}
}
}
As you can see I am sending data in a loop on the main thread and receiving data on the loop in the runnable thread. The main thread should continuously send "hello" to the receiver and output the message. However, no output is given?
Am I on the right track here? Is using threads the best way to do this? Is this even possible? And if so is there a better solution?