Android UDP hole punching - java

I am trying to make an streaming app and I want to use UDP. I would like the connection to be P2P. So I have a java tcp server running on google cloud, an android phone and my pc. When android connects to tcp server it will create a DatagramSocket on the server that will receive the packet android sends to get the port and ip. Same for the pc. Each client will get the other's client ip and port and each client will get the port that the server received (EG: android sends from port 18000, it will get other's client ip and port and port 18000). Then I close the initial DatagramSocket and open a new one that is bound to the port it gets from server (in our eg 18000). But the connection is never created between the pc and android (android is on 4G and pc on router , so different networks)
socket = new DatagramSocket(Integer.parseInt(po));
Here is how I create the P2P datgram socket, where po is 18000 (each client has different po - the android has 18000 and the pc has let's say 45000), I get those port from tcp server and is ok.
public void send() throws NumberFormatException, IOException
{
//only for testing
byte[] buffer = new byte[1024];
buffer = "test".getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length,InetAddress.getByName(ip),Integer.parseInt(port));
socket.send(packet);
}
Here is how i send data from the P2P datagram. The ip is the other's client public ip and the port is the other's client port that is listening.
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
byte[] buffer = new byte[64000];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
try {
socket.receive(packet);
//acum ca am primit
String ana = new String(packet.getData());
System.err.println("Am primit de la celalalt "+ana);
}
}
Here is the thread that listens for incoming packets.
The main problem is that this works but only when the client are on the same network as the server!Even if I both client are on the same netowk , but the server is on a different one, they won't receive anything. Data sent from TCP is 100% correct.
DatagramPacket packet= new DatagramPacket(buffer,buffer.length, InetAddress.getByName("server_ip"),port_main);
socket_udp.send(packet);
Here is how I send the UDP packet to the server in order to get the port back.
I tried using the same socket_udp ,without creating socket var again, it failed too.

Related

DatagramSocket not receiving / sending to the server in JAR

I have an Android server that I can connect to from my client in Java using DatagramSocket. It works perfectly fine when I run it from IntelliJ (the data is sent and received to and by the Android server). When I build from IntelliJ to a JAR file, I am unable to sometimes receive packets from the server, and sometimes I am unable to send any packets to the server. I have tried disabling the Firewall as well, even as far as using JLaunch to package the .jar file into an .exe and adding that to the Firewall to allow all incoming / outgoing traffic, but nothing has worked so far. It only works when I run the code through IntelliJ or Eclipse.
I connect to the server by getting the device's IP and the port I have bound the server to.
InetSocketAddress address = new InetSocketAddress(UserInterface.addressTextArea.getText(), PORT);
try {
serverSocket = new DatagramSocket(null);
serverSocket.connect(address);
} catch (SocketException | IllegalArgumentException socketException) {
socketException.printStackTrace();
}
Here is the code where I receive / send. I send an empty byte just so I can confirm I'm getting the packet on the server (which I do when I run from IntelliJ)
serverSocket.send(new DatagramPacket(new byte[0], 0));
// Receive packet from the Android server
byte[] receivedData = new byte[BUFFER_SIZE];
receivedPacket = new DatagramPacket(receivedData, receivedData.length);
serverSocket.receive(receivedPacket);
Here is the code on the Android server
/* Check if client is connected */
DatagramPacket client = new DatagramPacket(new byte[0], 0);
udpServerSocket.receive(client);
/* Read audioRecorder data and wrap it in a packet for UDP socket to send */
DatagramPacket packet = new DatagramPacket(
new byte[0],
0,
client.getAddress(),
client.getPort());
udpServerSocket.send(packet));
I'd like to be able to just run a .jar file instead of compiling and running from an IDE. Any help would be appreciated!

How does a "proxy server" work

I'm trying to implement a simple ProxyServer to analyze traffix between a connected device and the outside world.
The iPhone (for example) is configured to use a proxy to 192.168.1.10:8080.
My proxy server (on 192.168.1.10) will be listening on the port 8080.
The iPhone tries to connect to http://google.com:80, or ftp://somehost.com:21/ it sends a request to the proxy server (port 8080), which is supposed to contact google.com at port 80 and somehost at post 21.
So I figured it would be something like this:
//Accept incoming
ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//Log incoming requests
//Send to remote server on behalf of my device
Socket remote = new Socket(remoteHost, remotePort);
//forward the same data to remote client..
//wait for the reply
//send to my device
How to know the remote port/host to forward the request to?
What did I miss?
Thank you

Is it possible to transfer (a String, for example) from a TCP Server to a UDP Client?

I'm working on TCP and UDP just to learn the basics of how networks and protocols work in Java, and the task my professor has set me is to have the following:
A TCP Client that connects to a TCP Server, which communicates with a UDP Client that connects to a UDP Server, which gets/alters data from a Database.
I have everything set up and working, but right now the TCP Server calls the UDP Client as an object, and passes its information through a method call, rather than over the internet.
For TCP I'm using server sockets and input stream / buffered stream readers, and for the UDP I'm using datagram packets. So I'm not really sure how I can send from one to the other directly, or if it's even possible.
Thanks in advance for any help/advice/guidance!
Jona
**EDIT:
What I mean by passing through a method call:
//In TCPServer class
UDPClient udpc = new UDPClient();
String result = udpc.GetFromUDPServer(clientCommand);
//In UDPClient class
public class UDPClient{
public String GetFromUDPServer(String clientCommand){
try{
//Create a datagram socket
DatagramSocket sock = new DatagramSocket();
byte[] buffer = clientCommand.getBytes("UTF-8");
InetAddress ipAddress = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ipAddress, 447);
...

Multicast to directly connected WIFI device

I have a WIFI device, that I am experimenting with. From my macbook I can make a direct connection to the device over wifi. After I have WIFI connection I should be able to communicate with the device over multicast.
However, as soon as I try to send a datagram packet to the camera when I am connected I get some IOException:
java.io.IOException: Can't assign requested address
I reviewed some networking settings and found out that Multicast is enabled for my laptop, also I added the multicast address that is used (239.255.255.250) to the routing table. (Read this somewhere) Still no luck...
Why do I get this exception from my application?
Here is the code I use to connect:
DatagramSocket socket = null;
DatagramPacket packet = null;
try {
socket = new DatagramSocket();
InetSocketAddress iAddress = new InetSocketAddress("239.255.255.250", 1900);
packet = new DatagramPacket(sendData, sendData.length,iAddress);
socket.send(packet);
I think it has something to do with my network / setup.
When I reconnect to my wireless acces point, my app doesn't give this exception and I can see the package in my console:
MacBook-Pro-van-Roy:~ Roy$ sudo tcpdump -ni en1 host 239.255.255.250
Password:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on en1, link-type EN10MB (Ethernet), capture size 65535 bytes
19:54:18.688367 IP 192.168.1.34.57428 > 239.255.255.250.1900: UDP, length 129
19:54:18.789447 IP 192.168.1.34.57428 > 239.255.255.250.1900: UDP, length 129
19:54:18.890506 IP 192.168.1.34.57428 > 239.255.255.250.1900: UDP, length 129
InetSocketAddress is not a InetAddress (it's a SocketAddress). You probably want something like this:
InetAddress addr = InetAddress.getByName("239.255.255.250");
packet = new DatagramPacket(sendData, sendData.length, addr, 1900);
socket.send(packet);

Chat using TCP in Java

I am making a chat in Java which uses a TCP protocol.
I have a client and a server side.
To send a message to another user, I have to send the message to the server through my client, and the server has to send it to another client.
The server holds the addresses of both online users. When I send a private message, the server finds the ip and a port and creates a socket from them.
The problem is that it doesn’t work correctly.
Here’s the code:
int portNumber = 4444;
String host = "192.168.0.100”;
Socket link;
try {
link = new Socket(host, portNumber);
// Then I set to already created PrintWriter the outputstream
out = new PrintWriter(link.getOutputStream(), true);
} catch (Exception e) {}
// Unfortunately the server freezes here (it doesn't show anything).
How to solve this problem? Where dod I make a mistake?
Thank you in advance.
You shouldn't create a new Socket to send a message. Instead, use a socket of an existing connection.
The sequence should be the following:
Client A connects to the server (server stores the connection as SocketA).
Client B connects to the server (server stores the connection as SocketB).
Server reads a private message from SocketA. The message is addressed to client B.
Server finds the existing socket for client B. It's SocketB.
Server sends the message into SocketB.

Categories

Resources