web-dev-qa-db-ja.com

UDPソケットでのデータの送受信Java android

UDPソケットを介してデータを適切に送信できますが、データを受信して​​も、受信コマンドで待機し続けます。これは何が原因なのかわかりません。以下の私のコードを見てください。

Androidデバイスからサーバー側でデータを正しく受信できますが、サーバー側からAndroidデバイスにデータを送信すると受信しません。サーバーから他のクライアントにデータを送信するとき(たとえば、PCアプリケーション)、データを正しく受信して表示します。

class Task implements Runnable {
    @Override
    public void run() {
        try {
            String messageStr = "feed";
            int server_port = 8888;
            InetAddress local = InetAddress.getByName("10.0.2.2");
            int msg_length = messageStr.length();
            byte[] message = messageStr.getBytes();


            DatagramSocket s = new DatagramSocket();
           // 

            DatagramPacket p = new DatagramPacket(message, msg_length, local, server_port);
            s.send(p);//properly able to send data. i receive data to server

            for (int i = 0; i <= 20; i++) {
                final int value = i;
                message = new byte[30000];
                p = new DatagramPacket(message,message.length );
                s.receive(p); //keeps on waiting here but i am sending data back from server, but it never receives
                final byte[] data =  p.getData();;
                try {



                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        progressBar.setProgress(value);
                        imageView.setImageBitmap(BitmapFactory.decodeByteArray(data,0,data.length));
                    }
                });
            }
        }
        catch(Exception ex)
        {

        }
    }
}
17
user2539602

Eclipseのドキュメント:

このソケットからパケットを受信し、引数パックに保存します。パックのすべてのフィールドは、受信したデータに従って設定する必要があります。受信したデータがパケットバッファサイズより長い場合、切り捨てられます。このメソッドは、パケットが受信されるか、タイムアウトが期限切れになるまでブロックします。

s.receive(p);」コマンドは、データを受信するか、setSoTimeout(timeout)で設定されたタイムアウトが終了するまでスレッドをブロックします。

コミュニケーションをとるために2つのクラスを作成しました。最初のUDPサーバー:

import Java.net.DatagramPacket;
import Java.net.DatagramSocket;
import Android.annotation.SuppressLint;
import Android.content.Intent;
import Android.os.AsyncTask;
import Android.os.Build;

public class UDP_Server 
{
    private AsyncTask<Void, Void, Void> async;
    private boolean Server_aktiv = true;

    @SuppressLint("NewApi")
    public void runUdpServer() 
    {
        async = new AsyncTask<Void, Void, Void>() 
        {
            @Override
            protected Void doInBackground(Void... params)
            {   
                byte[] lMsg = new byte[4096];
                DatagramPacket dp = new DatagramPacket(lMsg, lMsg.length);
                DatagramSocket ds = null;

                try 
                {
                    ds = new DatagramSocket(Main.SERVER_PORT);

                    while(Server_aktiv)
                    {
                        ds.receive(dp);

                        Intent i = new Intent();
                        i.setAction(Main.MESSAGE_RECEIVED);
                        i.putExtra(Main.MESSAGE_STRING, new String(lMsg, 0, dp.getLength()));
                        Main.MainContext.getApplicationContext().sendBroadcast(i);
                    }
                } 
                catch (Exception e) 
                {
                    e.printStackTrace();
                } 
                finally 
                {
                    if (ds != null) 
                    {
                        ds.close();
                    }
                }

                return null;
            }
        };

        if (Build.VERSION.SDK_INT >= 11) async.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        else async.execute();
    }

    public void stop_UDP_Server()
    {
        Server_aktiv = false;
    }
}

受信したデータをBroadcastReceiverに送信すると、データを使って何でもできます。

そして今、私のクライアントはデータを送信します。このコードではブロードキャストを送信していますが、直接IPなどに送信するためのコードを変更しても問題ないと思います。

import Java.net.DatagramPacket;
import Java.net.DatagramSocket;
import Android.annotation.SuppressLint;
import Android.os.AsyncTask;
import Android.os.Build;

public class UDP_Client 
{
    private AsyncTask<Void, Void, Void> async_cient;
    public String Message;

    @SuppressLint("NewApi")
    public void NachrichtSenden()
    {
        async_cient = new AsyncTask<Void, Void, Void>() 
        {
            @Override
            protected Void doInBackground(Void... params)
            {   
                DatagramSocket ds = null;

                try 
                {
                    ds = new DatagramSocket();
                    DatagramPacket dp;                          
                    dp = new DatagramPacket(Message.getBytes(), Message.length(), Main.BroadcastAddress, Main.SERVER_PORT);
                    ds.setBroadcast(true);
                    ds.send(dp);
                } 
                catch (Exception e) 
                {
                    e.printStackTrace();
                }
                finally 
                {
                    if (ds != null) 
                    {   
                        ds.close();
                    }
                }
                return null;
            }

            protected void onPostExecute(Void result) 
            {
               super.onPostExecute(result);
            }
        };

        if (Build.VERSION.SDK_INT >= 11) async_cient.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        else async_cient.execute();
    }

次に、メインクラスからクラスをインスタンス化する方法を示します。

            //start UDP server
        Server = new UDP_Server();
        Server.runUdpServer();

        //UDP Client erstellen
        Client = new UDP_Client();

そして、ここでクライアントとメッセージを送信する方法。

                                    //Set message
                Client.Message = "Your message";
                                    //Send message
                Client.NachrichtSenden();

UDP_Serverを停止するには、Server.Server_aktivをfalseに設定するだけです。

上記のメッセージを設定するには、「setMessage(String message)」メソッドなどを書くこともできます。

22
Tim

ここでは、この投稿で、デバイス間または同じモバイルの2つのアプリケーション間でソケットを確立するための詳細なコードを見つけます。

以下のコードをテストするには、2つのアプリケーションを作成する必要があります。

両方のアプリケーションのマニフェストファイルで、以下の権限を追加します

<uses-permission Android:name="Android.permission.INTERNET" />

最初のアプリコード:UDPクライアントソケット

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <TableRow
        Android:id="@+id/tr_send_message"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:gravity="center"
        Android:layout_alignParentLeft="true"
        Android:layout_alignParentStart="true"
        Android:layout_alignParentTop="true"
        Android:layout_marginTop="11dp">

        <EditText
            Android:id="@+id/edt_send_message"
            Android:layout_width="0dp"
            Android:layout_height="wrap_content"
            Android:layout_weight="1"
            Android:layout_marginRight="10dp"
            Android:layout_marginLeft="10dp"
            Android:hint="Enter message"
            Android:inputType="text" />

        <Button
            Android:id="@+id/btn_send"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_marginRight="10dp"
            Android:text="Send" />
    </TableRow>

    <ScrollView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_alignParentLeft="true"
        Android:layout_alignParentStart="true"
        Android:layout_below="@+id/tr_send_message"
        Android:layout_marginTop="25dp"
        Android:id="@+id/scrollView2">

        <TextView
            Android:id="@+id/tv_reply_from_server"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:orientation="vertical" />
    </ScrollView>

</RelativeLayout>

DPClientSocketActivity.Java

import Android.os.Bundle;
import Android.os.Handler;
import Android.support.v7.app.AppCompatActivity;
import Android.view.View;
import Android.widget.Button;
import Android.widget.EditText;
import Android.widget.TextView;

import Java.io.IOException;
import Java.net.DatagramPacket;
import Java.net.DatagramSocket;
import Java.net.InetAddress;

/**
 * Created by Girish Bhalerao on 5/4/2017.
 */

public class UDPClientSocketActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView mTextViewReplyFromServer;
    private EditText mEditTextSendMessage;

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

        Button buttonSend = (Button) findViewById(R.id.btn_send);

        mEditTextSendMessage = (EditText) findViewById(R.id.edt_send_message);
        mTextViewReplyFromServer = (TextView) findViewById(R.id.tv_reply_from_server);

        buttonSend.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {

            case R.id.btn_send:
                sendMessage(mEditTextSendMessage.getText().toString());
                break;
        }
    }

    private void sendMessage(final String message) {

        final Handler handler = new Handler();
        Thread thread = new Thread(new Runnable() {

            String stringData;

            @Override
            public void run() {

                    DatagramSocket ds = null;
                    try {
                        ds = new DatagramSocket();
                        // IP Address below is the IP address of that Device where server socket is opened.
                        InetAddress serverAddr = InetAddress.getByName("xxx.xxx.xxx.xxx");
                        DatagramPacket dp;
                        dp = new DatagramPacket(message.getBytes(), message.length(), serverAddr, 9001);
                        ds.send(dp);

                        byte[] lMsg = new byte[1000];
                        dp = new DatagramPacket(lMsg, lMsg.length);
                        ds.receive(dp);
                        stringData = new String(lMsg, 0, dp.getLength());

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if (ds != null) {
                            ds.close();
                        }
                    }

                handler.post(new Runnable() {
                    @Override
                    public void run() {

                        String s = mTextViewReplyFromServer.getText().toString();
                        if (stringData.trim().length() != 0)
                            mTextViewReplyFromServer.setText(s + "\nFrom Server : " + stringData);

                    }
                });
            }
        });

        thread.start();
    }
}

2番目のアプリコード-UDPサーバーソケット

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Button
        Android:id="@+id/btn_stop_receiving"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="STOP Receiving data"
        Android:layout_alignParentTop="true"
        Android:enabled="false"
        Android:layout_centerHorizontal="true"
        Android:layout_marginTop="89dp" />

    <ScrollView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_below="@+id/btn_stop_receiving"
        Android:layout_marginTop="35dp"
        Android:layout_alignParentLeft="true"
        Android:layout_alignParentStart="true">

        <TextView
            Android:id="@+id/tv_data_from_client"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:orientation="vertical" />
    </ScrollView>

    <Button
        Android:id="@+id/btn_start_receiving"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="START Receiving data"
        Android:layout_alignParentTop="true"
        Android:layout_centerHorizontal="true"
        Android:layout_marginTop="14dp" />
</RelativeLayout>

DPServerSocketActivity.Java

import Android.os.Bundle;
import Android.os.Handler;
import Android.support.v7.app.AppCompatActivity;
import Android.view.View;
import Android.widget.Button;
import Android.widget.TextView;

import Java.io.IOException;
import Java.net.DatagramPacket;
import Java.net.DatagramSocket;

/**
 * Created by Girish Bhalerao on 5/4/2017.
 */

public class UDPServerSocketActivity extends AppCompatActivity implements View.OnClickListener {

    final Handler handler = new Handler();

    private Button buttonStartReceiving;
    private Button buttonStopReceiving;
    private TextView textViewDataFromClient;

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

        buttonStartReceiving = (Button) findViewById(R.id.btn_start_receiving);
        buttonStopReceiving = (Button) findViewById(R.id.btn_stop_receiving);
        textViewDataFromClient = (TextView) findViewById(R.id.tv_data_from_client);

        buttonStartReceiving.setOnClickListener(this);
        buttonStopReceiving.setOnClickListener(this);

    }

    private void startServerSocket() {

        Thread thread = new Thread(new Runnable() {

            private String stringData = null;

            @Override
            public void run() {

                byte[] msg = new byte[1000];
                DatagramPacket dp = new DatagramPacket(msg, msg.length);
                DatagramSocket ds = null;
                try {
                    ds = new DatagramSocket(9001);
                    //ds.setSoTimeout(50000);
                    ds.receive(dp);

                    stringData = new String(msg, 0, dp.getLength());
                    updateUI(stringData);

                    String msgToSender = "Bye Bye ";
                    dp = new DatagramPacket(msgToSender.getBytes(), msgToSender.length(), dp.getAddress(), dp.getPort());
                    ds.send(dp);

                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (ds != null) {
                        ds.close();
                    }
                }
            }

        });
        thread.start();
    }

    private void updateUI(final String stringData) {

        handler.post(new Runnable() {
            @Override
            public void run() {

                String s = textViewDataFromClient.getText().toString();
                if (stringData.trim().length() != 0)
                    textViewDataFromClient.setText(s + "\n" + "From Client : " + stringData);
            }
        });
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {

            case R.id.btn_start_receiving:

                startServerSocket();

                buttonStartReceiving.setEnabled(false);
                buttonStopReceiving.setEnabled(true);
                break;

            case R.id.btn_stop_receiving:

                //Add logic to stop server socket yourself

                buttonStartReceiving.setEnabled(true);
                buttonStopReceiving.setEnabled(false);
                break;
        }
    }
}
2
Girish Bhalerao