1

I wrote a simple UDP transfer between an Android App and Python Server. I know that the system is working because when I try to connect on a local ip address (192.168.X.X), the correct message is sent and recieved. However, this does not work when I try to use a public IP address. Does anyone know why and how I can try to fix this?

I am trying to implement UDP holepunching, having the server act as the target client of the Android one, but I cannot get the 2nd client's UDP packet to the Android one, it never gets picked up on the Android's side. Would having a 2nd machine act as the 2nd client fix this, or is my code incomplete?

Does my provider (T-Mobile) matter for UDP packet communication?

Client (Android):

public class CustomizeGatewayActivity extends ActionBarActivity {

    AsyncUDPReceiver aReceive = null;
    static TextView recieve = null;

    public static class PlaceholderFragment extends Fragment {
        EditText addressText, portText, messageText;
        Button udpsend, tcpsend;
        Socket socket = null;

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(
                    R.layout.fragment_customize_gateway, container, false);

            recieve = (TextView) rootView.findViewById(R.id.textView1);
            addressText = (EditText) rootView.findViewById(R.id.editText1);
            messageText = (EditText) rootView.findViewById(R.id.editText3);

            udpsend = (Button) rootView.findViewById(R.id.UDP);
            udpsend.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    AsyncUDPSend aSend = new AsyncUDPSend(addressText.getText().toString(), messageText.getText().toString());
                    aSend.execute();
                }
            });

        public class AsyncUDPSend extends AsyncTask<Void, Void, Void> {
            String address = "";
            String message = "";
            String response = "";
            AsyncUDPSend(String addr, String mes) {
                address = addr;
                message = mes;
            }

            @Override
        protected Void doInBackground(Void... params) {
            // TODO Auto-generated method stub
            DatagramSocket dsocket = null;
            try {
                dsocket = new DatagramSocket();
                dsocket.setSoTimeout(10000);
                InetAddress dest = InetAddress.getByName(address);
                DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), dest, 5001);
                dsocket.send(packet);
                System.out.println("Sent");

                byte[] resp = new byte[1024];
                DatagramPacket recv = new DatagramPacket(resp, resp.length);
                System.out.println("Waitng for Response");
                dsocket.receive(recv);
                System.out.println("Received");
                response = new String(recv.getData());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    response = "IOException: " + e.toString();
                    System.out.println(response);
                } finally {
                    if (dsocket != null) {
                        dsocket.close();
                    }
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                recieve.setText(response);
                super.onPostExecute(result);
            }
        }

    @Override
    protected void onResume() {
        super.onResume();
        aReceive = new AsyncUDPReceiver();
        aReceive.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        aReceive.kill();
    }

    public class AsyncUDPReceiver extends Thread {
        boolean keepRunning = true;
        String response = "";

        Runnable updateText = new Runnable(){
            public void run() {
                if(aReceive == null && recieve == null)
                    return;
                recieve.setText(response);
            }
        };

        public void run() {
            android.os.Debug.waitForDebugger();
            System.out.println("running");
            DatagramSocket dsock = null;
            byte[] message = new byte[1024];
            DatagramPacket dpack = new DatagramPacket(message, message.length);
            try {
                dsock = new DatagramSocket(5002);
                System.out.println(dsock.toString());
                while(keepRunning) {
                    dsock.receive(dpack);
                    response = new String(dpack.getData());
                    System.out.println(response);
                    runOnUiThread(updateText);
                }
            } catch (SocketException e) {
                // TODO Auto-generated catch block
                response = "SocketException: " + e.toString();
                System.out.println(response);
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                response = "IOException: " + e.toString();
                System.out.println(response);
                e.printStackTrace();
            } finally {
                if(dsock != null)
                    dsock.close();
            }
        }

        public void kill() {
            keepRunning = false;
        }
    }
}

Server (Python):

class ThreadedUDPRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request[0].strip().decode("utf-8")
        print("{} Recieved: ".format(self.client_address) + data)
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        response = data.upper()
        sock.sendto(bytes(response, "utf-8"), self.client_address)
        print("{} Sent: {}".format(self.client_address,response))

class ThreadedUDPServer(socketserver.ThreadingMixIn, socketserver.UDPServer): 
    pass

if __name__ == "__main__":
    # Port 0 means to select an arbitrary unused port
    HOST, PORT = "", 5000

    udpserver = ThreadedUDPServer((HOST,PORT+1), ThreadedUDPRequestHandler)
    udp_thread = threading.Thread(target=udpserver.serve_forever)
    udp_thread.daemon = True
    udp_thread.start()
    print("UDP serving at port", PORT+1)

    while True:
        pass
    udpserver.shutdown()
putty174
  • 305
  • 5
  • 19
  • See my answer to a similar question [here][1] [1]: http://stackoverflow.com/a/25095781/3199595 – Malt Aug 05 '14 at 07:14
  • I realize that NAT's are causing me issues with this, and I want to implement UDP hole punching to overcome the blocked packets, but even with the Android and the Server sending UDP packets at each other, only the Android ones make it through to the server, and the Server ones never reach the Android client. Do you know of any solutions to this, or can you recommend me some direction to look for answers? – putty174 Aug 05 '14 at 08:18
  • Ah, that brings me to another answer I wrote: http://stackoverflow.com/a/25096374/3199595 As for NAT traversal techniques, I'd start by looking at existing frameworks that do the work for you. Writing hole punching or implementing protocols like IGD (https://en.wikipedia.org/wiki/Internet_Gateway_Device_Protocol) is a pain. I assume android has an existing solution for this, since Google does push notifications (notifications from the server to android devices, some of which are probably behind NAT) – Malt Aug 05 '14 at 08:44

1 Answers1

0

Are you supplying the expected value to InetAddress.getByName(address);

Also since you are trying to do something in background,it will be better if you run a service with wake lock so that you eliminate errors caused due to killing of process.

rupesh jain
  • 3,410
  • 1
  • 14
  • 22
  • Supplying the expected value to which part, the Sender or the Receiver? The Sender has the right IP address, and my server receives the message on the right port. I assume the server is also sending on the right port because I wrote a test client that worked properly. When I give the IP Address to the Receiver as an InetAddress, I get SocketException: java.net.BindException: bind failed: EADDRNOTAVAIL (Cannot assign requested address) for dsock = new DatagramSocket(5002, address); in AsyncUDPReceiver's run() method. – putty174 Jul 29 '14 at 19:04
  • Try using some different port no..Some port nos are reserved for system – rupesh jain Jul 29 '14 at 19:08
  • Which system are you talking about, Android or PC? I know that the ports I am using are not used by my server's system. Generally ports below 1024 are reserved for the system, anything above is free to use. – putty174 Jul 29 '14 at 19:12
  • run this command and check the port range-adb shell cat /proc/sys/net/ipv4/ip_local_port_range.For my phone its between 32768 and 61000..When I use port no as 50000 it works. – rupesh jain Jul 29 '14 at 19:25
  • I ran the command and it showed 32768 to 61000. I changed the reply port to 50002, but it still doesn't work. – putty174 Jul 29 '14 at 23:06