2013-10-23 202 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