简体   繁体   English

无法通过Internet从PC服务器接收Android上的UDP数据

[英]Unable to receive UDP data on Android from PC server over the Internet

I am currently exploring UDP packet transmission in Java to create a multiplayer game on Android. 我目前正在探索Java中的UDP数据包传输,以在Android上创建多人游戏。 I succeeded at exchanging packets within my Nexus 4 by using the usual "127.0.0.1" and I also succeeded at exchanging packets between my PC server and my Android client in my local network. 我成功地通过使用通常的“127.0.0.1”在我的Nexus 4中交换数据包,并且我也成功地在我的本地网络中的PC服务器和我的Android客户端之间交换数据包。 But since I will want my game to be playable on the Internet, I want my Android client to be able to exchange packets with my PC server when they aren't on the same local network. 但由于我希望我的游戏可以在互联网上播放,我希望我的Android客户端能够与我的PC服务器在不在同一本地网络上时交换数据包。 This is where I am struggling. 这是我在努力的地方。

My setup : A PC server connected with my home Internet connection and a Nexus 4 connected with a 3G network. 我的设置:连接家庭互联网连接的PC服务器和连接3G网络的Nexus 4。

First, my PC server starts listening on the port 10000 and my Android client opens a socket to receive server's packets on port 10001. Then, the Android client sends a packet to the PC server to its current public address "173.246.12.125" on port 10000. The PC server receives the packet and sends a response to the sender on port 10001. But the Android client never receives the response. 首先,我的PC服务器开始侦听端口10000,我的Android客户端打开一个套接字,以便在端口10001上接收服务器的数据包。然后,Android客户端将一个数据包发送到PC服务器,并将其发送到端口上的当前公共地址“173.246.12.125” 10000.PC服务器接收数据包并在端口10001上向发送方发送响应。但Android客户端从不接收响应。

Here is my PC server code : 这是我的PC服务器代码:

public class UDPServer {
    private final static int SERVER_PORT = 10000;
    private final static int CLIENT_PORT = 10001;

    public static void main(String[] args) {
        InetAddress clientAddr = null;
        DatagramSocket socket = null;
        try {
            //Initializing the UDP server
            System.out.println(String.format("Connecting on %s...", SERVER_PORT));
            socket = new DatagramSocket(SERVER_PORT);
            System.out.println("Connected.");
            System.out.println("====================");
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        }

        while(true){
            try {
                //Listening
                byte[] buf = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                System.out.println("Listening...");
                socket.receive(packet);

                //Getting client address from the packet we received
                clientAddr = packet.getAddress();
                System.out.println("Received: '" + new String(packet.getData()).trim() + "' from "+clientAddr.toString());

                //Sending response
                byte[] message = ("Hello Android").getBytes();
                DatagramPacket response = new DatagramPacket(message, message.length, clientAddr, CLIENT_PORT);
                DatagramSocket clientSocket = new DatagramSocket();
                System.out.println("Sending: '" + new String(message) + "'");
                clientSocket.send(response);
                System.out.println("Response sent.");
                System.out.println("--------------------");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

And here are my Android client classes : 这是我的Android客户端类:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Receiver()).start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(new Client()).start();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

}

public class Receiver implements Runnable {
    private final static int LISTENING_PORT = 10001;

    @Override
    public void run() {
        try {
            //Opening listening socket
            Log.d("UDP Receiver", "Opening listening socket on port "+LISTENING_PORT+"...");
            DatagramSocket socket = new DatagramSocket(LISTENING_PORT);
            socket.setBroadcast(true);
            socket.setReuseAddress(true);

            while(true){
                //Listening on socket
                Log.d("UDP Receiver", "Listening...");
                byte[] buf = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
                Log.d("UDP", "Received: '" + new String(packet.getData()).trim() + "'");
            }
        } catch (Exception e) {
            Log.e("UDP", "Receiver error", e);
        }
    }
}

public class Client implements Runnable {
    private final static String SERVER_ADDRESS = "173.246.12.125";//public ip of my server
    private final static int SERVER_PORT = 10000;

    @Override
    public void run() {
        try {
            //Preparing the socket
            InetAddress serverAddr = InetAddress.getByName(SERVER_ADDRESS);
            DatagramSocket socket = new DatagramSocket();

            //Preparing the packet
            byte[] buf = ("Hello computer").getBytes();
            DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddr, SERVER_PORT);

            //Sending the packet
            Log.d("UDP", String.format("Sending: '%s' to %s:%s", new String(buf), SERVER_ADDRESS, SERVER_PORT));
            socket.send(packet);
            Log.d("UDP", "Packet sent.");
        } catch (Exception e) {
            Log.e("UDP", "Client error", e);
        }
    }
}

The server's console is showing the IP of the client : 服务器的控制台显示客户端的IP:

Connecting on 192.168.1.126:10000...
Connected.
====================
Listening...
Received: 'Hello computer' from /204.48.72.68
Sending: 'Hello Android'
Response sent.
--------------------
Listening...

The packet seems to come from the address 204.48.72.68, but if I go on whatismyip.com on my Android, it shows me 96.22.246.97... I don't know where 204.48.72.68 is coming from... 该数据包似乎来自地址204.48.72.68,但如果我在Android上继续使用whatismyip.com,它会显示96.22.246.97 ...我不知道204.48.72.68来自哪里......

I am not sure if the problem is that my listening socket on my Android client is not good or if the PC server does not send the response to the correct address. 我不确定问题是我的Android客户端上的监听套接字不好还是PC服务器没有将响应发送到正确的地址。 Could someone points me what am I doing wrong? 有人能指出我做错了什么吗?

Thank you 谢谢

I came across a similar issue, but I was using TCP Sockets instead of UDP. 我遇到了类似的问题,但我使用的是TCP套接字而不是UDP。 My intense was sending files directly to a mobile. 我强烈要求将文件直接发送到手机。 In LAN this worked pretty much. 在局域网中,这非常有效。 It appears, that's not possible to send data to listening sockets, when your phone is connected to internet using the mobile connection. 看来,当您的手机使用移动连接连接到互联网时,无法将数据发送到收听套接字。 I've read on some pages (sry dont have any links anymore), that incoming connections on a mobile phone is blocked by the telecommunications provider. 我已经阅读了一些页面(sry没有任何链接),移动电话上的传入连接被电信提供商阻止。 My workaround was to create outgoing connections to the server and use the bidirectional possiblities of tcp sockets. 我的解决方法是创建到服务器的传出连接并使用tcp套接字的双向可能性。 Maybe you can use your "working" datagram socket, to exchange data with your mobile. 也许您可以使用“工作”数据报套接字与手机交换数据。 Here is an example, which i had found: http://itucet.blogspot.de/2011/03/java-bidirectional-data-transfer-using.html 这是一个例子,我找到了: http//itucet.blogspot.de/2011/03/java-bidirectional-data-transfer-using.html

Same code working well for me, Have an issue when tried with emulator but its works fine if you use any android mobile . 相同的代码对我来说效果很好,尝试使用模拟器时遇到问题,但如果您使用任何Android移动设备,它的工作正常。

The reason for the issue is android emulator and your computer are not in same subnet . 问题的原因是android模拟器和您的计算机不在同一个子网中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM