【问题标题】:How to have a continuous receive UDP in an async function for android?如何在 android 的异步函数中连续接收 UDP?
【发布时间】:2014-01-29 18:39:30
【问题描述】:

我正在尝试建立一个 UDP 发送/接收应用程序。我发送一条消息,服务器回复,然后服务器可能会随着时间的推移发送更多信息。我创建了一个线程来发送消息,并创建了另一个异步线程来不断地在后台检查新消息。但是,我没有正确接收消息。如果我有一个恒定的接收数据包馈送它可以正常工作,但是当接收是随机的时它不起作用。

例如: 端口 1:不断向我的客户端发送数据,所以我每秒都会收到新的数据包。结果很好,我的应用程序显示了每个新数据包。我的“接收更新”甚至像“接收”一样滴答作响。 “正在接收……” “正在接收……”

端口 2:我随机接收数据包。只有当我继续单击我的发送按钮时,它才会显示它们。我的接收进度点仅在我按下发送按钮时迭代。有时一个数据包会闪烁然后消失。

我正在尝试使端口 2 工作。在发布进度后,我尝试让我的 inbackground() 函数休眠 2 秒,但这并没有帮助。我真的很困惑如何制作它,所以我可以不断地接收 UDP 数据包。这是我的代码。

编辑:现在端口 2 显示正确,消息不只是闪烁和消失。但是,我的接收...进度点更新真的很慢。我的问题是,在我的“doInBackground”函数中,我有无限的while循环,那个循环不是一直执行得很快吗?所以即使没有新消息,我仍然会在循环结束时发布,这样我的“正在接收..”进度点应该向右移动?

再次编辑:我实际上没有对源代码进行任何更改,只是一些布局的东西,现在端口 2 不再工作了。它不显示任何新接收或接收更新栏。

如果我使用恒定馈送转到端口 1,那么一切都会完美更新...

我尝试查看其他问题,但不知道该怎么做。感谢您的帮助!

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.provider.Settings.Global;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
Button button;
TextView txt1, txtH, txtE, txtER, txtUpdate;
String msg;
CharSequence oldMsg="a";
Integer updateCount=0;
Activity mActivity;
DatagramSocket socket;
boolean msgSent = false;
boolean errorSend = false;
boolean errorReceive = false;



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    txt1 = (TextView) findViewById(R.id.textView2);
    txtH = (TextView) findViewById(R.id.textView1);
    txtE = (TextView) findViewById(R.id.textView6);
    txtER = (TextView) findViewById(R.id.textView8);
    txtUpdate = (TextView) findViewById(R.id.textView9);

            //I start my async class here
            new receiveUDP().execute();

    button = (Button) findViewById(R.id.button1);

            //When I click this, I send a message
    button.setOnClickListener(new View.OnClickListener() {      

        @Override
    public void onClick(View v) {

        Thread sendThread = new Thread(){
            public void run(){
                try{
                    byte[] data ="Some MSG".getBytes();
                    InetAddress address = InetAddress.getByName("Some address");

                    DatagramPacket pack = null;
                    pack = new DatagramPacket(data,data.length, address, somePort);
                    socket.send(pack);
                    msgSent=true;


                    } catch (Exception e){
                        boolean errorSend = true;
                    }
                }
            };
            sendThread.start();
            try {
                sendThread.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            if (msgSent){
                 txtH.setText("SENT!");
             }

        }
    });

    if (errorSend){
        txtE.setText("Error Sending Socket");
    }       


}

public class receiveUDP extends AsyncTask <Void, CharSequence, Void>{

    @Override
    protected Void doInBackground(Void... params) {
                    //Constantly check to see if we received a new packet.
        while (true){
            try{    //if no socket, create a new socket
                if (socket == null){
                    socket = new DatagramSocket(somePort, InetAddress.getByName("address"));
                    socket.setBroadcast(true);
                }               


                byte[] buf = new byte[2500];
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
                                    //Get the data of the packet to be a string
                msg = new   String(packet.getData(),0,packet.getLength());

            } catch (Exception e){
                errorReceive=true;
                e.printStackTrace();

            }

                publishProgress(msg);

        }

    }

     protected void onProgressUpdate(CharSequence...progress) {
         updateCount++;
         // If no errors, and if new message is different than old message
                     // Then change the text field to show new message. 
         if(!(errorReceive)){
            if(!(oldMsg.equals(progress[0]))){
                 txt1.setText(progress[0]);
                 oldMsg = progress[0];
            }

         }else
         {
             txtER.setText("Error Receiving");
         }

                     //Progress dots...
         if(updateCount==1){
             txtUpdate.setText("Receiving.");
         }
         else if(updateCount==2){
             txtUpdate.setText("Receiving..");
         }
         else {
             txtUpdate.setText("Receiving...");
             updateCount=0;
         }


     }

}



}

【问题讨论】:

  • 您的网络配置是什么?如果服务器在 Internet 上,并且 Android 设备在 NAT 之后,您可能会丢失来自服务器的一些数据包,因为路由器“忘记”了相应的翻译记录。为了避免这种情况,设备需要定期向服务器发送数据包,以刷新路由器上的 NAT 转换记录。

标签: java android multithreading asynchronous udp


【解决方案1】:

我这样做是成功的(考虑到我收到的消息是一个字符串,使用以下符号来划分参数|

出于这个原因,您会看到我在收到消息后使用 split 命令

p.s.:不要用模拟器,用真机试试。

p.p.s.:在您创建活动时使用 startReceiveUdp 开始收听,然后在您的 gui 线程中使用 stopReceiveUdp 停止收听,就在关闭您的活动之前(我在 onDismiss sub 中使用它,覆盖它)。

ReceiveSocket receiveSocket;

void startReceiveUdp()
{
    if (receiveSocket==null) {
        receiveSocket=new ReceiveSocket();
        receiveSocket.execute("");
    }
}

void stopReceiveUdp()
{
    if (receiveSocket!=null) receiveSocket.cancel(true);
}

private class ReceiveSocket extends AsyncTask<String, String, String> {


    DatagramSocket clientsocket;

    @Override
    protected String doInBackground(String... params) {
        while (true) {
            try {
                publishProgress(receiveMessage());
                if(isCancelled()) break;      
            } catch (Exception e) {
                //
            }

        }
        return "";
    }

    String[] receiveMessage(){

        String[] rec_arr = null;
        try {
              int port = 8081;
              if (clientsocket == null) clientsocket=new DatagramSocket(port);

              byte[] receivedata = new byte[30];

              DatagramPacket recv_packet = new DatagramPacket(receivedata, receivedata.length);
              //Log.d("UDP", "S: Receiving...");
              clientsocket.receive(recv_packet);
              String rec_str = new String(recv_packet.getData()); //stringa con mesasggio ricevuto
              rec_str= rec_str.replace(Character.toString ((char) 0), "");
              //Log.d(" Received String ",rec_str);
              //InetAddress ipaddress = recv_packet.getAddress();
              //int port = recv_packet.getPort();
              //Log.d("IPAddress : ",ipaddress.toString());
              //Log.d(" Port : ",Integer.toString(port));

              rec_arr=rec_str.split("\\|");


              return rec_arr;

        } catch (Exception e) {
          Log.e("UDP", "S: Error", e);
        }
        return rec_arr;
    }


    @Override
    protected void onPostExecute(String result) {
        //
    }

    @Override
    protected void onPreExecute() {}

    @Override
    protected void onProgressUpdate(String... rec_arr) {
        //ricevi la stringa,
        //splittala
        //esegui l'azione richiesta sulla GUI



          if (rec_arr.length>1){
              String clientType=rec_arr[0]; 
              String command=rec_arr[1]; 

              if(command.contentEquals("go")){
                  //press button go
                  startAction(null);
              }


          }


    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 2018-02-17
    • 1970-01-01
    • 2012-11-19
    相关资源
    最近更新 更多