簡體   English   中英

UDP打孔:PC到Android的UDP連接不適用於非本地地址

[英]UDP holepunching: PC-to-Android UDP connection does not work with nonlocal addresses

我在Android應用程序和Python服務器之間編寫了一個簡單的UDP傳輸。 我知道系統正在工作,因為當我嘗試連接本地IP地址(192.168.XX)時,將發送並接收正確的消息。 但是,當我嘗試使用公共IP地址時,這不起作用。 有誰知道為什么以及如何解決這個問題?

我正在嘗試實現UDP穿孔,使服務器充當Android客戶端的目標客戶端,但是我無法將第二個客戶端的UDP數據包發送到Android客戶端,因此它永遠不會在Android方面被接收。 將第二台計算機作為第二個客戶端可以解決此問題,還是我的代碼不完整?

我的提供商(T-Mobile)對UDP數據包通信有影響嗎?

客戶端(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;
        }
    }
}

服務器(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()

您是否正在向InetAddress.getByName(address)提供期望的值?

另外,由於您嘗試在后台執行某些操作,因此最好使用喚醒鎖運行服務,以消除由於進程終止而導致的錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM