2013-10-23 201 views
10

我能夠通過UDP套接字正確地發送我的數據,但是當我收到數據時,它一直在等待接收命令我不知道是什麼造成這個 請看看在我的代碼下面發送和接收數據在UDP套接字java android

我能夠在服務器端從android設備正確recive數據,但是當我從服務器端發送數據到android設備它不會收到。但是當我從服務器發送數據到任何其他客戶端如PC應用中接收和rpoperly顯示數據

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) 
     { 

     } 
    } 
} 
+0

我現在知道這是一個有點老,但你有沒有弄清楚這一個?與你陷入同樣的​​問題。我正在向服務器獲取數據,但是當我將其發回時什麼都沒有。 – patrickdamery

+1

嘗試在UDP情況下減少每次發送的數據大小,這爲我解決了問題。 – user2539602

+0

我想了一會兒,但發送和接收端的數據大小必須相同,否則你可以得到波濤洶涌的音頻 – patrickdamery

回答

21

文檔在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; 
    } 
} 

我接收到的數據發送到廣播接收器,有你可以做你想要的數據什麼都。

現在我的客戶端發送數據。在這段代碼中,我發送了一個廣播,但我認爲改變發送到直接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)」方法或類似的東西。

我希望這會幫助你=)。 最後抱歉我的英文不好。 :D

+0

我收到一個錯誤,「無法解析符號主」在像Main.BroadcastAddress和Main.SERVER_PORT。有沒有辦法來解決這個問題? – ksivakumar

+1

這些是我在另一個.java文件(稱爲Main)中聲明的2個常量。你可以用他們想要的值替換它們。 – Tim

+0

你會如何調用Main.MainContext.getApplicationContext()。sendBroadcast(i);在沒有使用Main類的第一類中? – ksivakumar

0

在這篇文章中,您將找到在設備之間建立套接字的詳細代碼,或者在同一個移動設備上的兩個應用程序之間建立套接字的詳細代碼。

您必須創建兩個應用程序才能測試下面的代碼。

在這兩個應用程序的清單文件,添加以下權限

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

1日應用代碼: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> 

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

第二個應用程序代碼 - 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> 

UDPServerSocketActivity.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; 
     } 
    } 
} 
+0

多數民衆贊成在良好的,但它只收到1字符串然後你需要停止服務器,並重新啓動它,並再次發送有新的字符串 – Eazyz