5

私は現在、Androidでマルチプレイヤーゲームを作成するために、JavaでのUDPパケット送信を調査しています。通常の「127.0.0.1」を使用してNexus4内でパケットを交換することに成功しました。また、ローカルネットワーク内のPCサーバーとAndroidクライアント間でパケットを交換することにも成功しました。ただし、ゲームをインターネットでプレイできるようにしたいので、Androidクライアントが同じローカルネットワーク上にないときにPCサーバーとパケットを交換できるようにします。これは私が苦労しているところです。

私のセットアップ:自宅のインターネット接続に接続されたPCサーバーと、3Gネットワ​​ークに接続されたNexus4。

まず、PCサーバーがポート10000でリッスンを開始し、Androidクライアントがソケットを開いてポート10001でサーバーのパケットを受信します。次に、AndroidクライアントがPCサーバーにパケットをポートの現在のパブリックアドレス「173.246.12.125」に送信します。 10000. PCサーバーはパケットを受信し、ポート10001で送信者に応答を送信します。ただし、Androidクライアントは応答を受信しません。

これが私の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();
            }
        }
    }

}

そして、これが私の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);
        }
    }
}

サーバーのコンソールにクライアントのIPが表示されています。

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

パケットはアドレス204.48.72.68から来ているようですが、Androidでwhatismyip.comにアクセスすると、96.22.246.97と表示されます...204.48.72.68がどこから来ているのかわかりません...

Androidクライアントのリスニングソケットが適切でないことが問題なのか、PCサーバーが正しいアドレスに応答を送信しないのかがわかりません。誰かが私に何が間違っているのか指摘してもらえますか?

ありがとうございました

4

2 に答える 2

2

同様の問題が発生しましたが、UDPの代わりにTCPソケットを使用していました。私の熱心なのは、ファイルをモバイルに直接送信することでした。LANでは、これはほとんど機能しました。携帯電話がモバイル接続を使用してインターネットに接続されている場合、リスニングソケットにデータを送信することはできないようです。私はいくつかのページで読んだことがあります(もうリンクはありません)、携帯電話での着信接続は電気通信プロバイダーによってブロックされています。私の回避策は、サーバーへの発信接続を作成し、tcpソケットの双方向の可能性を使用することでした。たぶん、あなたはあなたの「働く」データグラムソケットを使ってあなたの携帯電話とデータを交換することができます。これが私が見つけた例です:http: //itucet.blogspot.de/2011/03/java-bidirection-data-transfer-using.html

于 2013-02-16T23:48:21.317 に答える
1

同じコードが私にとってはうまく機能しています。エミュレータで試してみると問題が発生しますが、Androidモバイルを使用している場合は正常に機能します。

この問題の理由は、Androidエミュレーターであり、コンピューターが同じサブネットにないためです。

于 2013-05-16T05:38:31.583 に答える