2014-01-29 43 views
1

我正在嘗試建立一個UDP發送/接收應用程序。我發送一條消息,服務器迴應,然後服務器可以隨時間發送更多信息。我創建了一個線程發送消息,另一個Async線程連續檢查新消息的背景。但是,我沒有正確接收消息。如果我有一個恆定的接收數據包饋送,它工作正常,但當接收數據是隨機的時它不起作用。如何在android的異步函數中持續接收UDP?

例如: 端口1:不斷髮送數據到我的客戶端,所以我每秒都會收到新的數據包。結果很好,我的應用程序顯示每個新的數據包。我的「接收更新」甚至會像「接收」一樣發送。 「Receiving ..」「Receiving ...」

端口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; 
     } 


    } 

} 



} 
+0

什麼是您的網絡配置?如果服務器在Internet上,並且Android設備位於NAT後面,則可能會丟失來自服務器的一些數據包,因爲路由器「忘記」了相應的翻譯記錄。爲避免這種情況,設備需要定期向服務器發送數據包以刷新路由器上的NAT轉換記錄。 – vadipp

回答

1

我就是這麼做的成功(認爲我收到的消息是使用下面的符號來劃分參數字符串|爲這個原因,你看,我使用分割命令,一旦接收到消息

PS:不使用仿真器,嘗試在真正的手機

PPS:使用startReceiveUdp開始收聽時,您創建的活動,然後使用stopReceiveUdp在GUI線程停止監聽,就在解僱你的行爲ivity(我在onDismiss子裏面使用它,覆蓋它)。

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


      } 


    } 
}