I am working on a simple audio streamer with multicast. I wrote serer and client on the same machine, so I worked with localhost and multicast-groups. The system works on one machine but when I tried to use another PC as the server, I can't get them to connect. Here is the situation:
The client first knocks on a tcp-server which lets the client know the multicasting-group IP an port. After this, the client starts listining to the address via multicastSocket.receive();.
Here are the important bits from the system:
(I left out the exceptions and other non-important stuff in the following code)
Server
Important to know is that the "LAN-Connection" is the name of my network interface on the servers system.
int multicastPort = 8888;
InetAddress multicastIP = InetAddress.getbyName("228.5.6.7");
InetSocketAddress multicastAddress = new inetSocketAddress( multicastIP, multicastPort );
NetworkInterface multicastInterface = NetworkInterface.getByName( "LAN-Connection" );
MulticastSocket multicastSocket = new MulticastSocket( multicastPort );
multicastSocket.joinGroup( multicastAddress, multicastIP);
while(true) {
byte [] buffer = audioIn.readBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, multicastIP, multicastPort);
multicastSocket.send(packet );
}
Client
The client requests the multicast-IP and Port from the server. (a tcp-server-thread handles this) Like with the server "LAN-Connection" is the name of the clients network interface.
int multicastPort = server.request("port");
String multicastIP_String = server.request("IP");
InetAddress multicastIP = InetAddress.getbyName(multicastIP_String );
InetSocketAddress multicastAddress = new inetSocketAddress( multicastIP, multicastPort );
NetworkInterface multicastInterface = NetworkInterface.getByName( "LAN-Connection" );
MulticastSocket multicastSocket = new MulticastSocket( multicastPort );
multicastSocket.joinGroup( multicastAddress, multicastIP);
while(true) {
byte [] buffer = new byte[2048];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
multicastSocket.receive(packet);
}
The TCP connection for requesting / sending the multicast IP and port works. An application called CurrPorts also tells me, that the correct ports get reserved, however, with wireshark, I can't find any packets sended / received neither on the clients system nor the server system. (I watched port 88 but there is no traffic,...)
Both PCs are connected to one router(D-Link DIR-635) and i guess I would have noticed If multicasting woudl be blocked by the router, right?
What am I missing? Shoudl I try different ports or IPs or could something block the packets? I only use windows firewall and I even turned this thing off for a test.
Here is a running example. I have no problem running this on the same machine but when I run the server on my laptop in the same network, nothing works.
Server
package multicastserver;
import java.net.*;
public class MulticastServer {
public static void main(String[] args) {
int multicastPort = 8888;
try {
InetAddress multicastIP = InetAddress.getByName("228.5.6.7");
InetSocketAddress multicastAddress = new InetSocketAddress( multicastIP, multicastPort );
NetworkInterface multicastInterface = NetworkInterface.getByName( "LAN-Verbindung" );
MulticastSocket multicastSocket = new MulticastSocket( multicastPort );
multicastSocket.joinGroup(multicastAddress, multicastInterface);
int counter = 0;
while(true) {
String message = "This is server, packet nr. " + counter;
counter++;
byte [] buffer = message.getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, multicastIP, multicastPort);
multicastSocket.send(packet);
System.out.println("Sended: " + message);
Thread.sleep(500);
}
} catch (Exception e) {
System.out.println(e);
return;
}
}
}
Client
package multicastclient;
import java.net.*;
public class MulticastClient {
public static void main(String[] args) {
int multicastPort = 8888;
try {
InetAddress multicastIP = InetAddress.getByName("228.5.6.7");
InetSocketAddress multicastAddress = new InetSocketAddress( multicastIP, multicastPort );
NetworkInterface multicastInterface = NetworkInterface.getByName( "LAN-Verbindung" );
MulticastSocket multicastSocket = new MulticastSocket( multicastPort );
multicastSocket.joinGroup(multicastAddress, multicastInterface);
while(true) {
byte [] buffer = new byte[40];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
multicastSocket.receive(packet);
buffer = packet.getData();
String message = new String(buffer, "UTF-8");
System.out.println("Received: " + message);
}
} catch (Exception e) {
System.out.println(e);
return;
}
}
}
Related
I need to send and receive in multicast.
This is my Sender:
public static void main(String[] args) {
MulticastSocket socket = null;
try {
socket = new MulticastSocket(3575);
int n = 1;
while (n <= 100) {
byte[] buf = new byte[256];
// non aspetta la richiesta
String dString = new Date().toString();
buf = dString.getBytes();
// invia il messaggio in broadcast
InetAddress group = InetAddress.getByName("230.0.0.1");
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, 3575);
socket.send(packet);
System.out.println ("Broadcasting: "+dString);
Thread.sleep(1000);
n++;
}
socket.close();
}catch(Exception e) { e.printStackTrace(); socket.close();}
}//main
This is my Receiver:
public static void main(String[] args) throws IOException {
MulticastSocket socket = new MulticastSocket(3575);
InetAddress group = InetAddress.getByName("230.0.0.1");
socket.joinGroup(group);
DatagramPacket packet;
for (int i = 0; i < 100; i++) {
byte[] buf = new byte[256];
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData()).trim();
System.out.println("Time: " + received);
}
socket.leaveGroup(group);
socket.close();
}//main
When I run them, the Receiver does not receive anything.
I tried on two different PC ( both with Windows) with AntiVirus and firewall disabled. I also tried with different LAN: my router, my phone hotspot.
It does not work neither on local machine.
How can I solve the problem?
Thanks
I compiled and ran your code on my laptop, with the sender and receiver on the same machine. It works. (Fedora 26 Linux, Java 1.8.0_171)
It seems that the problem is something to do with your networking, not the application code. So, since this not a programming problem, I think you would be better off asking this Question on the ServerFault site ... where they specialize in networking, etcetera.
I have a sample code as below and the socket is bound to IP 10.10.88.11 and port 9876. I tested with the 2 conditions with wireshark as below. Both PCs are in the same subnet.
Send UDP packet from the same pc (10.10.88.11) - UDP Server able to receive
Send UDP packet from another pc ( 10.10.88.10) - UDP Server unable to receive but Wireshark (at 10.10.88.11) able to capture the packets
I have searched the internet but can't find a solution for this. Is there anything i did wrong in creating the InetScoketAddress?
import java.io.*;
import java.net.*;
public class UDPServer {
public static void main(String args[]) throws Exception {
InetSocketAddress address = new InetSocketAddress("10.10.88.11", 9876);
DatagramSocket serverSocket = new DatagramSocket(address);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
System.out.println("Waiting to receive");
serverSocket.receive(receivePacket);
String sentence = new String( receivePacket.getData());
System.out.println("RECEIVED: " + sentence);
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
}
}
}
I believe Wireshark is able to grab packets before they are evaluated by the firewall, meaning that you will detect them but they will never reach the java app. Did you try deactivating your firewall ?
I have a setup, where 2 pc's(let's say A and B) are behind NAT of each pubic IP. So they each have their own different private IP . I am using a server in between, which will interchange the IP Address and Port no. of A and B. They also exchange their internal Port no..!
So basically this is the setup.
Client A and B run the following code:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Clientnew {
public static void main(String[] args) throws Exception {
// prepare Socket
DatagramSocket clientSocket = new DatagramSocket();
for(int i = 1;i<10;i++){
// prepare Data
byte[] sendData = "Hello".getBytes();
// send Data to Serverc
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, InetAddress.getByName("27.251.62.27"), 7070);
clientSocket.send(sendPacket);
//send localip and local port to server
System.out.println("Sending Local info");
// InetAddress IPAddressLocal = clientSocket.getLocalAddress();
int PortLocal = clientSocket.getLocalPort();
String msgInfoOfClient1 = PortLocal+":PortLocal";
byte[] newData = msgInfoOfClient1.getBytes();
System.out.println(msgInfoOfClient1);
DatagramPacket sendLocalPacket = new DatagramPacket(newData, newData.length, InetAddress.getByName("27.251.62.27"), 7070);
clientSocket.send(sendLocalPacket);
// receive External Data ==> Format:"<External IP of other Client>-<External Port of other Client>"
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
clientSocket.receive(receivePacket);
// Convert Response to IP and Port
String response = new String(receivePacket.getData());
String[] splitResponse = response.split("-");
InetAddress External_IP = InetAddress.getByName(splitResponse[0].substring(1));
int External_Port = Integer.parseInt(splitResponse[1]);
// output converted Data for check
System.out.println("External IP: " + External_IP + " External PORT: " + External_Port);
// receive Internal Data ==> Format:"<Internal IP of other Client>-<Internal Port of other Client>"
DatagramPacket anotherPacket = new DatagramPacket(new byte[1024], 1024);
clientSocket.receive(anotherPacket);
// Convert Response to IP and Port
response = new String(anotherPacket.getData());
splitResponse = response.split(":");
// InetAddress Internal_IP = InetAddress.getByName(splitResponse[0].substring(1));
int Internal_Port = Integer.parseInt(splitResponse[0]);
// output converted Data for check
System.out.println(" Internal PORT: " + Internal_Port);
}
}
}
And the code on Server S is:-
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Servernew {
public static void main(String args[]) throws Exception {
DatagramSocket serverSocket2 = new DatagramSocket(6588);
// Waiting for Connection of Client1 on Port 7070
// ////////////////////////////////////////////////
// open serverSocket on Port 7070
DatagramSocket serverSocket1 = new DatagramSocket(7070);
for(int i= 1; i<10;i++){
System.out.println("Waiting for Client 1 on Port "
+ serverSocket1.getLocalPort());
// receive Data
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket1.receive(receivePacket);
// Get IP-Address and Port of Client1
InetAddress IPAddress1 = receivePacket.getAddress();
int port1 = receivePacket.getPort();
String FirstmsgInfoOfClient1 = IPAddress1 + "-" + port1 + "-";
System.out.println("Client1 External: " + FirstmsgInfoOfClient1);
// Get Message from Client
DatagramPacket anotherPacket = new DatagramPacket(new byte[1024], 1024);
serverSocket1.receive(anotherPacket);
// Decode the String
String response = new String(anotherPacket.getData());
String[] splitResponse = response.split(":");
// InetAddress LocalIP1 = InetAddress.getByName(splitResponse[0].substring(1));
int LocalPort1 = Integer.parseInt(splitResponse[0]);
// int LocalPort1 = Integer.parseInt(splitResponse[1]);
// String msgInfoOfClient1 = PortLocal+":PortLocal";
String SecondmsgInfoOfClient1 = LocalPort1+":LocalPort1";
System.out.println("Client1 Internal: " + SecondmsgInfoOfClient1);
// System.out.println(response);
// Waiting for Connection of Client2 on Port 6588
// ////////////////////////////////////////////////
// open serverSocket on Port 6588
// DatagramSocket serverSocket2 = new DatagramSocket(6588);
System.out.println("Waiting for Client 2 on Port "
+ serverSocket2.getLocalPort());
// receive Data
receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket2.receive(receivePacket);
// GetIP-Address and Port of Client1
InetAddress IPAddress2 = receivePacket.getAddress();
int port2 = receivePacket.getPort();
String FirstmsgInfoOfClient2 = IPAddress2 + "-" + port2 + "-";
System.out.println("Client2 External:" + FirstmsgInfoOfClient2);
// Get Message from Client
anotherPacket = new DatagramPacket(new byte[1024], 1024);
serverSocket2.receive(anotherPacket);
// Decode the String
response = new String(anotherPacket.getData());
splitResponse = response.split(":");
// InetAddress LocalIP1 = InetAddress.getByName(splitResponse[0].substring(1));
int LocalPort2 = Integer.parseInt(splitResponse[0]);
// int LocalPort1 = Integer.parseInt(splitResponse[1]);
//
String SecondmsgInfoOfClient2 = LocalPort2+":LocalPort2";
System.out.println("Client2 Internal: " + SecondmsgInfoOfClient2);
// Send the Information to the other Client
/////////////////////////////////////////////////
// Send Information of Client2 to Client1
serverSocket1.send(new DatagramPacket(FirstmsgInfoOfClient2.getBytes(),
FirstmsgInfoOfClient2.getBytes().length, IPAddress1, port1));
serverSocket1.send(new DatagramPacket(SecondmsgInfoOfClient2.getBytes(),
SecondmsgInfoOfClient2.getBytes().length, IPAddress1, port1));
// Send Infos of Client1 to Client2
serverSocket2.send(new DatagramPacket(FirstmsgInfoOfClient1.getBytes(),
FirstmsgInfoOfClient1.getBytes().length, IPAddress2, port2));
serverSocket2.send(new DatagramPacket(SecondmsgInfoOfClient1.getBytes(),
SecondmsgInfoOfClient1.getBytes().length, IPAddress2, port2));
System.out.println("-----------------\n");
System.out.println("---------------------");
}
//close Sockets
serverSocket1.close();
serverSocket2.close();
}
}
And the Output is that they are exchanging their Internal and External Ports and Public IP perfectly well.
So the Question is How do I use this information to open a TCP connection between A and B? How do I implement a TCP Punch hole using Java?
P.S: It is utmost necessary to be a TCP connection and that I use Java to do so.
Open two ServerSocket on S, accepting connections from each of A and B (port 62000 and 31000 respectively). When accept in each case returns a Socket instance then cross the InputStream and OutputStream of each one into one another using PipedOutputStream and PipedInputStream. You'll need to have a thread for each.
I'm having a weird problem, let's consider the following code :
import java.net.*;
import java.util.Enumeration;
public class Main{
public static void main(String args[]) throws Exception {
Inet4Address myIp = (Inet4Address)Inet4Address.getByName(Main.getLanIp());
InetSocketAddress myAddr = new InetSocketAddress(myIp, LocalportNumber);
if(myIp == null){
throw new Exception();
}
DatagramSocket socket = new DatagramSocket(myAddr);
socket.setReuseAddress(true);
InetAddress IPAddress = InetAddress.getByName("239.xxx.xxx.xxx");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = "PAYLOAD";
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, distantPortNumber);
DatagramPacket receivePacket = new DatagramPacket(receiveData, 1024);
socket.send(sendPacket);
System.out.println("Packet sent");
socket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
socket.close();
}
static public String getLanIp() throws SocketException{
InetAddress inet_addr = null;
NetworkInterface cur = null;
for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();){
cur = interfaces.nextElement();
try {
if (cur.isLoopback())
{
continue;
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("interface " + cur.getName());
for (InterfaceAddress addr : cur.getInterfaceAddresses()){
inet_addr = addr.getAddress();
if ( !( inet_addr instanceof Inet4Address)){
continue;
}
System.out.println(" address: " + inet_addr.getHostAddress() + "/" + addr.getNetworkPrefixLength());
System.out.println(" broadcast address: " + addr.getBroadcast().getHostAddress());
}
}
return inet_addr.getHostAddress();
}
}
Execution trace :
"""
interface eth0
address: 192.168.0.20/24
broadcast address: 192.168.0.255
Packet sent
"""
When I run the preceding code, a packet is sent, the server answers but I still block on the receive method, I can see the incoming packet on wireshark reaching my computer. But when I try a : "netstat -npl", I see a java process listening on the port localPort. I tried a "nc -vvv -u 9393" from remote (lan) and then typed random sentences ... Nothing happened. I tried the same on local (with my external IP, with my loopback IP), same problem. Is there a list of known problems which could block the received udp packets between the kernel and the jvm ?
I found my problem : my iptable firewall ... I was blocking all the incoming traffic which was not an answer to my outgoing traffic. That's why I saw the traffic on wireshark but I didn't reached the java socket...
So the solution was to open my firewall -_-"
Client A
import java.io.*;
import java.net.*;
import java.util.*;
public class ClientA
{
final private static int PORT = 5005; // arbitrarily assigned port to use
public static void main(String args[]) throws
IOException
{
DatagramSocket socket = new DatagramSocket(PORT); // create new connection on that port
while (true)
{
byte buffer[] = new byte[256]; // data buffer
DatagramPacket packet = new DatagramPacket(buffer, buffer.length); // new packet containing buffer
socket.receive(packet); // look for packet
String clientBMsg = new String(packet.getData()); // get data from received packet
InetAddress address = packet.getAddress(); // get address of received packet
System.out.println("ClientB at " + address + " says " + clientBMsg);
buffer = null;
String msgString = "I'm ClientA, vegetables are fun";
buffer = msgString.getBytes(); // put String in buffer
int port = packet.getPort(); // get port of received packet
packet = new DatagramPacket(buffer, buffer.length, address, port); // create new packet with this data
socket.send(packet); // send packet back containing new buffer!
System.out.println("Message Sent");
socket.close();
}
}
}
Client B
import java.io.*;
import java.net.*;
public class ClientB
{
final private static int PORT = 5005; // arbitrarily assigned port - same as server
public static void main(String args[]) throws
IOException {
// if (args.length == 0) { // requires host
// System.err.println
// ("Please specify host");
// System.exit(-1);
// }
// String host = args[0]; // user defined host
DatagramSocket socket = new DatagramSocket(); // open new socket
String host = "localhost";//"86.0.164.207";
byte message[] = new byte[256]; // empty message
String msgString = "Hello, I'm client B and I like trees";
message = msgString.getBytes(); // put String in buffer
InetAddress address = InetAddress.getByName(host); // determines address
System.out.println("Sending to: " + address); // tells user it's doing something
DatagramPacket packet = new DatagramPacket(message, message.length, address, PORT); // create packet to send
socket.send(packet); // send packet
System.out.println("Message Sent");
message = new byte[256];
packet = new DatagramPacket(message, message.length);
socket.receive(packet); // wait for response
String clientAreply = new String(packet.getData());
System.out.println("ClientA at " + host + " says " + clientAreply);
socket.close();
}
}
I don't understand why this works over localhost but when I put my IP address in, it just sends the message and nothing is received.
Can anyone point me in the right direction here?
Thank you!
You should use DatagramSocket's bind method to bind it to your internet interface, otherwise it only listens on 127.0.0.1 or localhost. Like this:
DatagramSocket socket = new DatagramSocket(null);
socket.bind(new InetSocketAddress(InetAddress.getByName("your.ip.add.ress"),5005);
In case you are behind your router then your should listen on the local IP address given to you by the router and use port forwarding to this address in your router settings.
I can suggest using Socket Test tool with TCP and UDP Sockets:
http://sockettest.sourceforge.net/
I used it to trouble shoot issues with a 2-way socket program. You can end-to-end test your link with two SocketTest programs and the compare results, etc. Very useful.