web-dev-qa-db-fra.com

Envoyer et recevoir des données sur le socket UDP Java android

Je peux envoyer correctement mes données via le socket UDP, mais lorsque je reçois des données, il continue d'attendre à la commande de réception, je ne sais pas ce qui cause cela. Veuillez consulter mon code ci-dessous.

Je suis en mesure de recevoir correctement les données côté serveur de l'appareil Android, mais lorsque j'envoie des données côté serveur à Android il ne reçoit pas. Mais lorsque j'envoie des données du serveur à tout autre client, par exemple une application PC, il reçoit et affiche les données correctement.

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

Documentation dans Eclipse:

Reçoit un paquet de cette socket et le stocke dans le pack d'arguments. Tous les champs du pack doivent être définis en fonction des données reçues. Si les données reçues sont plus longues que la taille du tampon de paquets, elles sont tronquées. Cette méthode se bloque jusqu'à ce qu'un paquet soit reçu ou qu'un délai expire.

La commande "s.receive(p);" bloque le thread jusqu'à ce qu'il reçoive les données ou que le délai défini avec setSoTimeout (délai) soit terminé.

J'ai fait 2 cours pour que ma communication se fasse. Premier serveur 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;
    }
}

J'envoie les données reçues à un BroadcastReceiver et là vous pouvez faire ce que vous voulez avec les données.

Et maintenant mon client envoie les données. Dans ce code, j'envoie une diffusion, mais je pense que ce ne sera pas un problème de changer le code pour envoyer à une adresse IP directe ou quelque chose.

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();
    }

Et voici comment vous instanciez les classes de votre classe principale.

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

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

Et voici comment envoyer un message au client.

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

Pour arrêter UDP_Server, définissez simplement Server.Server_aktiv sur false.

Pour définir le message ci-dessus, vous pouvez également écrire une méthode "setMessage (String message)" ou quelque chose comme ça.

22
Tim

Ici, dans cet article, vous trouverez le code détaillé pour établir la socket entre les appareils ou entre deux applications dans le même mobile.

Vous devez créer deux applications pour tester le code ci-dessous.

Dans les deux applications fichier manifeste, ajoutez l'autorisation ci-dessous

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

1er code d'application: UDP Client Socket

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();
    }
}

2e code d'application - socket du serveur 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