I'm developing some peer 2 peer app for my class and I was told for letting servers to discover each other they have to Multicast to their UDP port 1110 and listen to their UDP port 1110. I wrote the code like below for doing that. for testing I run 2 servers which both send and receive. but it seems nothing working. where do you think my problem is ?
I put 2 servers in 2 different folders. and I assigned to IP addresses to my NIC like this ifconfig eth0:3 192.168.0.11 netmask 255.255.255.0 up how should I tell each server about the new ip address?
BroadcastListner
class BroadcastListner implements Callable<Object> {
int PORT = 1110;
String IP = "255.255.255.255";
MulticastSocket socket ;
DatagramPacket packet;
InetAddress IPAD;
byte data[] = null ; //////////////change size
int numOfNodes;
BroadcastListner(String IP, int numOfNodes) {
try {
this.numOfNodes = numOfNodes;
this.IP = IP;
IPAD = InetAddress.getByName(IP);
socket = new MulticastSocket(PORT);
packet = new DatagramPacket(data,data.length);
} catch (Exception e) {
e.printStackTrace();
}
}
BroadcastListner(int numOfNodes) {
try{
this.numOfNodes = numOfNodes;
// this.IP = IP;
IPAD = InetAddress.getByName(IP);
socket = new MulticastSocket(PORT);
packet = new DatagramPacket(data,data.length);
} catch (Exception e) {
e.printStackTrace();
}
}
public String call() {
try{
socket.joinGroup(IPAD);
} catch (Exception e) {
e.printStackTrace();
return "";
}
while(true) {
try {
socket.receive(packet);
String str = new String(packet.getData());
System.out.println(" Time signal received from"+
packet.getAddress() + " Time is : " +str);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
//socket.leaveGroup(IPAD);
//socket.close();
//return "";
}
}
BroadcastSender
class BroadcastSender implements Callable<Object> {
int PORT = 1110;
String IP = "255.255.255.255";
MulticastSocket socket;
DatagramPacket packet;
InetAddress IPAD;
byte[] data = "IAmAServer".getBytes();
//int numOfNodes;
String str = "IAmAServer";
BroadcastSender(String IP) {
try {
// this.numOfNodes = numOfNodes;
this.IP = IP;
IPAD = InetAddress.getByName(IP);
socket = new MulticastSocket();
} catch (Exception e) {
e.printStackTrace();
}
}
BroadcastSender() {
try{
// this.numOfNodes = numOfNodes;
// this.IP = IP;
IPAD = InetAddress.getByName(IP);
socket = new MulticastSocket();
} catch (Exception e) {
e.printStackTrace();
}
}
public String call() {
try {
socket.joinGroup(IPAD);
socket.setTimeToLive(10);
} catch (Exception e) {
e.printStackTrace();
return "";
}
while(true) {
try {
Thread.sleep(2000);
packet = new DatagramPacket (data,str.length(),IPAD,PORT);
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
//return "";
}
}
You need to try the broadcast address of 192.168.0.255
An alternative is to use a multi-cast instead of broadcast address like 224.x.x.x which is not tied to a specific subnet.
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'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.
I have to send any size file from a client to a server using UDP. I send the datagrams in byte arrays. I split the file and send the datagrams. I know the server receives the datagrams but my problem is on how to put the datagrams in a File again. This is my code for the Client (I'll just put the code that splits and sends the file, I used JavaFX for the client).
Thank you all in advance.
private void sendFile(ActionEvent event) {
ArrayList<byte[]> listDatagrams;
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
String serverName = "localhost";
InetAddress IPserver;
int serverPort = 6789;
byte[] data;
DatagramPacket request;
IPservidor = InetAddress.getByName(serverName);
data = Files.readAllBytes(file.toPath());
listDatagrams = splitFile(data);
for(byte[] datagrama : listDatagrams){
request= new DatagramPacket(datagrama, datagrama.length, IPserver, serverPort );
socket.send(request);
}
try {
fileOuputStream.write(respuesta.getData());
} finally {
fileOuputStream.close();
}
} catch (SocketException e) {
System.out.println("SocketException: " + e.getMessage());
} catch (IOException e) {
System.out.println("IOException: " + e.getMessage());
} finally {
if (socket != null) {
socket.close();
}
}
}
This is the method I used to split the File:
public ArrayList<byte []> splitFile(byte[] file){
ArrayList<byte[]> data = new ArrayList<>();
double nPartitions;
byte[] partition= new byte[MAX];
if(file.length>MAX){
nPartitions =Math.ceil(file.length/MAX);
for(int i=0; i<=nPartitions; i++)
for(int j=0; j<MAX; j++){
if(i==0){
if(j==file.length-1)
break;
partition[j]=file[j];
}else if(i==1){
if((j+MAX)==file.length-1){
break;
}else{
partition[j]=file[(j+MAX)];
}
}else{
if((j+MAX)>=file.length-1)
break;
partition[j]=file[(i*(MAX+1))+j];
}
}
data.add(partition);
}
}
return data;
}
And the code for the server:
public static void main(String args[]) {
DatagramSocket socket = null;
ArrayList<DatagramPacket> data= new ArrayList<>();
try {
int serverPort= 6789;
socket = new DatagramSocket(serverPort);
byte[] buffer;
buffer = new byte[5000];
while (true) {
DatagramPacket request;
request= new DatagramPacket(buffer, buffer.length);
socket.receive(request);
//I add the datagramas to an array list but I am not sure how to re arrenge them into a File. The server should always be on and be able to receive a second file if I want to
data.add(request);
}
} catch (SocketException e) {
System.out.println("SocketException: " + e.getMessage());
} catch (IOException e) {
System.out.println("IOException: " + e.getMessage());
} finally {
if (socket != null) {
socket.close();
}
}
}
Note: I know TCP is better but this is for school so
Only local client can connect only to server.
Client side code:
public InetAddress ipAddress;
private DatagramSocket socket;
public Client()
{
try
{
this.socket = new DatagramSocket();
this.ipAddress = getIpAddress();
}
catch (SocketException e)
{
e.printStackTrace();
}
}
public void run()
{
while(true)
{
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 1331);
try
{
socket.send(packet);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
private InetAddress getIpAddress()
{
String ipAddress;
try
{
URL url = new URL("http://checkip.amazonaws.com/");
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
ipAddress = br.readLine();
} catch (IOException e)
{
e.printStackTrace();
ipAddress = "null";
}
try
{
return InetAddress.getByName(ipAddress);
}
catch (UnknownHostException e)
{
e.printStackTrace();
return null;
}
}
public static void main(String args[])
{
Client client = new Client();
client.start();
}
Server side code:
private DatagramSocket socket;
public Server()
{
try
{
this.socket = new DatagramSocket(null);
socket.bind(new InetSocketAddress(getIpAddress(), 1331));
System.out.println(socket.getInetAddress());
}
catch (SocketException e)
{
e.printStackTrace();
}
}
public void run()
{
while(true)
{
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try
{
socket.receive(packet);
System.out.println("aa");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
private InetAddress getIpAddress()
{
try
{
return InetAddress.getByName("0.0.0.0");
}
catch (UnknownHostException e)
{
e.printStackTrace();
return null;
}
}
public static void main(String args[])
{
Server server = new Server();
server.start();
}
I tried to off my firewall, off Windows Defender, add NAT to router.
Also i checked if port is foreign port in netstat.
The only way to work fine server is to change ipAddress of client to "localhost"
Then code is working fine.
Is there and method how can i add address to server and players can connect to server with only ip address?
In order to connect the server multiple other computers, you should set the clients IP address to the address of the server's computer.
How to know what's the IP address of the server computer?
In the computer where the server installed:
Windows: go to CMD and then type ipconfig you need the IPv4 address.
Mac: go to terminal and then type ifconfig you need inet address.
I recently started making a 2D java game, and started making a tcp server 2 days ago, now that all my other issues are fixed, I would like to address the fact that the client can only connect to the server when it is on the same device and using the devices static ip, though it cannot connect using my wan ip address, I have port forwarded and I have checked on many port-checker websites and they all can see my server, my firewall is also disabled, yet the client can't see the server using the wan ip, I made a mine craft server on the same port (Minecraft servers are also tcp) and others were able to connect using my wan ip. When a client does try to connect using my wan ip, it gives a Connection Refused exception. What am i doing wrong?
Client (Can't connect to server over nat):
package com.diedericksclan.main.network;
import java.io.*;
import java.net.*;
import java.util.Enumeration;
public class ClientThread extends Thread {
private ClientHandler client;
private Socket socket;
private InetSocketAddress address;
private int megabyte = 1024 * 1024;
private DataInputStream in;
private DataOutputStream out;
public ClientThread(ClientHandler client, InetSocketAddress address) {
this.client = client;
this.address = address;
socket = new Socket();
try {
socket.setSendBufferSize(megabyte);
socket.setSendBufferSize(megabyte);
socket.setTcpNoDelay(true);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(this.getIP(), 0));
System.out.println(socket.getLocalAddress().getHostAddress() + ":" + socket.getLocalPort() + " is a new client!");
socket.connect(address);
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private InetAddress getIP() throws SocketException {
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
NetworkInterface ni;
while (nis.hasMoreElements()) {
ni = nis.nextElement();
if (!ni.isLoopback() && ni.isUp()) {
for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
if (ia.getAddress().getAddress().length == 4) {
return ia.getAddress();
}
}
}
}
return null;
}
long starttime;
long endtime;
long overall;
public void run() {
byte[] data;
while(true) {
try {
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
data = new byte[in.readInt() - 4];
in.read(data);
client.parsePacket(data, socket.getInetAddress(), socket.getPort());
endtime = System.nanoTime();
overall = endtime - starttime;
//System.out.println("CLIENT >> SERVER >> CLIENT - Time was: " + overall + " nano seconds!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public synchronized void sendData(byte[] data) {
try {
try { socket.connect(address); } catch (IOException e) {}
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
starttime = System.nanoTime();
out.writeInt(data.length + 4);
out.write(data);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void serverShutdown() {
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server (Can be seen by everything but client):
package com.diedericksclan.main.network;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import com.diedericksclan.main.network.handling.PlayerMP;
public class ServerThread extends Thread {
private ServerHandler server;
private ServerSocket dataSocket;
private Socket socket;
private InetSocketAddress address;
private int megabyte = 1024 * 1024;
private int dedicated = 1024;
public int RAM = megabyte * dedicated;
private ArrayList<Client> clients = new ArrayList<Client>();
public ServerThread(ServerHandler server, String serverIP, int ram, int backlog) throws Exception {
super(serverIP);
this.server = server;
this.dedicated = ram;
String ip = "localhost";
int port = 2048;
if(serverIP.contains(":")) {
ip = serverIP.split(":")[0];
port = Integer.parseInt(serverIP.split(":")[1]);
} else {
ip = serverIP;
port = 2048;
}
this.dataSocket = new ServerSocket();
this.dataSocket.setReuseAddress(true);
this.address = new InetSocketAddress(InetAddress.getByName(ip), port);
this.dataSocket.bind(address, 0);
}
public ServerThread(ServerHandler server, String ip) throws Exception {
this(server, ip, 1024, 0);
}
public void run() {
while(true) {
try {
socket = dataSocket.accept();
socket.setKeepAlive(true);
socket.setSendBufferSize(megabyte);
socket.setSendBufferSize(megabyte);
socket.setTcpNoDelay(true);
socket.setReuseAddress(true);
InetSocketAddress clientAddress = new InetSocketAddress(socket.getInetAddress(), socket.getPort());
System.out.println("Starting");
if(getClients().size() > 0) {
for(Client c : getClients()) {
if(clientAddress != c.socket.getLocalSocketAddress()) {
Client client = new Client(socket, clientAddress);
getClients().add(client);
client.start();
System.out.println("Added new client!");
break;
}
}
} else {
Client client = new Client(socket, clientAddress);
getClients().add(client);
client.start();
System.out.println("Added new client!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public synchronized void sendData(byte[] data, InetAddress IPaddress, int port) {
if(this.getClient(new InetSocketAddress(IPaddress, port)) != null) {
this.getClient(new InetSocketAddress(IPaddress, port)).sendData(data);
}
}
public void serverShutdown() {
try {
this.dataSocket.close();
if(this.socket != null) this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public int getClientIndex(InetSocketAddress address) {
int index = 0;
for(Client c : getClients()) {
if(c.socket.getRemoteSocketAddress().equals(address)) {
break;
}
index++;
}
System.out.println("Getting client index...");
return index;
}
public synchronized ArrayList<Client> getClients() {
return this.clients;
}
private Client getClient(InetSocketAddress address) {
for(Client c : getClients()) {
if(c.socket.getRemoteSocketAddress().equals(address)) {
return c;
}
}
return null;
}
public class Client extends Thread {
DataInputStream in;
DataOutputStream out;
Socket socket;
public Client(Socket sock, InetSocketAddress IPaddress) {
try {
socket = sock;
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
try {
byte[] data = new byte[in.readInt() - 4];
in.read(data);
server.parsePacket(data, socket.getInetAddress(), socket.getPort());
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendData(byte[] data) {
try {
out.writeInt(data.length + 4);
out.write(data);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I would really appreciate it if someone could help.
-Regards
user.....
Port forwarding does not work when both machines are on the same LAN. Here's why:
The client sends a packet to the server's WAN address. It goes to the router. (Because machines on a LAN use the router to reach any WAN address.)
The router port forwards the packet to the server's LAN address. The source IP address is not changed, it's still the client's LAN address. (That's what port forwarding does.)
The server accepts the TCP connection by sending packets to the address it saw as the source address of the packets it received -- the client's LAN address. And, of course it gives them the only source IP address it can, it's LAN address.
Packets sent from the server to the client's LAN address go directly to the client, the router has no opportunity to NAT them because they are sent to the client's LAN address. (Here's where things go awry. If the client had been on another network, the packets would have gone to the router, since that's how the server reaches other networks.)
The client receives packets from the server's LAN address, but it was expecting packets from the server's WAN address (since that's what it sent them to), so the connection cannot work.
If you want to connect to the server from other machines on the LAN you must either connect to the server's LAN address or use some form of dual-NAT such as hairpin NAT -- port forwarding won't work.
I'm having some problems receiving a String from a multicast.
It's the first time i'm using UDP multicast in Java.
I'm making a multiclient application over a LAN.
So i'm using Local Ip addresses.
I need the clients to find the server's IP address so they can send their data, requests, etc.
I let the server sent out a multicast with his own IP as a string every 5 seconds.
The clients should be able to receive it.
The problem is that they don't receive anything.
I'm testing with 2 devices so i don't need to use localhost.
Here's some of my code:
Server side:
public class MulticastIpSender extends Thread{
private String serverIp;
private int port;
private String multicastAddress;
private long WAITING_TIME = 5000; // 5 seconden
private DatagramSocket socket;
public MulticastIpSender(String serverIp, int port, String multicastAddress) throws SocketException {
super();
this.serverIp = serverIp;
this.port = port;
this.multicastAddress = multicastAddress;
socket = new DatagramSocket(port);
}
public void run() {
while(true){
try {
byte[] buf = new byte[256];
buf = serverIp.getBytes();
InetAddress group = InetAddress.getByName(multicastAddress);
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port);
socket.send(packet);
System.out.println("sent IP("+serverIp+") to group("+group+") on port "+port);
sleep(WAITING_TIME);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I put this method in the main class:
private void sendIpAddressToListeners() {
try {
multicastIpSender = new MulticastIpSender(serverIp,PORT,"230.0.0.1");
multicastIpSender.run();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I get the serverIp like this:
String hostName = InetAddress.getLocalHost().getHostName();
InetAddress addrs[] = InetAddress.getAllByName(hostName);
if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress()) {
myIp = addr.getHostAddress();
}
}
System.out.println ("\nIP = " + myIp);
return myIp;
on this device it gives me 192.168.1.2
CLIENT SIDE:
multicastSocket = new MulticastSocket(PORT);
InetAddress address = InetAddress.getByName(MULTICAST_ADDRESS);
multicastSocket.joinGroup(address);
DatagramPacket serverIpPacket;
byte[] buf = new byte[256];
serverIpPacket = new DatagramPacket(buf, buf.length);
while(receivedIp ==null){
multicastSocket.receive(serverIpPacket);
receivedIp = new String(serverIpPacket.getData(), 0, serverIpPacket.getLength());
System.out.println("received server ip: " + receivedIp);
}
!! PORT = 4445 in both server and client
I hope somebody can help me with this or can explain a better way to do this.
Send a normal DatagramPacket on broadcast address, the packet will be received by all hosts in local network (with same network configuration, important part is mask)
Use calculator to check your broadcast address, this one works good: http://www.subnet-calculator.com/