【问题标题】:I am not getting a udp package from the server Android Java我没有从服务器 Android Java 获取 udp 包
【发布时间】:2019-10-07 15:04:19
【问题描述】:

我想连接到服务器,接收 UDP 消息。我认为连接是正确的,但它不会从服务器接收到我的 udp 包。服务器在网络上发送 udp 消息,但我无法接收?所以它只会连接到服务器,为什么它不向我发送消息。我不需要先向服务器发送消息。

 public class TestUdpClient implements Runnable {

    private DatagramSocket sock;
    private int port = 1200;
    private String inetAddress = "122.17.4.6";
    private SocketAddress remoteAddress;
    byte[] message = new byte[200];
    private ByteBuffer b;
    private String signature;



    public void run() {

        try {
            Log.d(TAG, "S: Connecting...");
            InetSocketAddress localSocketAddress = new InetSocketAddress(0);
            remoteAddress = new InetSocketAddress(inetAddress, port);
            sock = new DatagramSocket(localSocketAddress);
            sock.connect(remoteAddress);
           System.out.println(sock.isConnected());
            boolean running = true;
            while (running) {

                // Prepare a UDP-Packet that can contain the data we want to receive
                DatagramPacket packet = new DatagramPacket(message, message.length);
                Log.d(TAG, "S: Receiving...");

                // Receive the UDP-Packet
                sock.receive(packet);
                Log.d(TAG, "S: Received: '" + new String(packet.getData()) + "'");
                synchronized (this) {
                    wait(500);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            Log.e("connection","No connection was made");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

主活动

View.OnClickListener buttonConnectOnClickListener =
    new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {

            try {
                udpClient = new UdpClient(serverAdres,poortNummer);
            } catch (IOException e) {
                e.printStackTrace();
            }


            new Thread(new ClientSendAndListen()).start();
            buttonConnect.setEnabled(false);
        }
    };

【问题讨论】:

  • 你能分享错误堆栈跟踪吗?
  • android.os.NetworkOnMainThreadException 在 android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513) 在 java.net.AbstractPlainDatagramSocketImpl.connect(AbstractPlainDatagramSocketImpl.java:132) 在 java.net。 DatagramSocket.connectInternal(DatagramSocket.java:169) at java.net.DatagramSocket.connect(DatagramSocket.java:517) at com.ict.barcodescanner.UdpClient.(UdpClient.java:31) at com.ict.barcodescanner .MainActivity$1.onClick(MainActivity.java:48)
  • Android 不允许在主线程上进行网络操作。创建一个 AsyncTask 并从doInBackground() 调用udpClient = new UdpClient(serverAdres,poortNummer);(另请参阅此处stackoverflow.com/a/19541474/5312102
  • UDP 是无连接的,调用sock.connect() 只会过滤入站数据包,因此只有从特定对等 IP/端口接收到的数据包才会返回给您。但是要真正通知服务器您已准备好接收,您通常必须先向服务器发送一个数据包,以便它知道您甚至存在,除非服务器正在向整个网络子网发送广播数据包。话虽如此,您是否使用像 Wireshark 这样的数据包嗅探器嗅探网络以确保服务器实际上开始发送非空白数据包?
  • 另外,为什么您的线程会在每次循环迭代时创建一个新的DatagramSocketDatagramPacket?它应该在进入循环之前创建一次DatagramSocketDatagramPacket。循环应该只是调用sock.receive()(并忽略SocketTimeoutException 错误),直到应用准备好终止线程。

标签: java android sockets udp connection


【解决方案1】:

Android sdk 不允许主线程中的网络请求。您必须创建一个新线程来发出网络请求。为简单起见,您可以实现 android sdk 提供的 AsyncTask。

https://developer.android.com/training/articles/perf-anr

https://developer.android.com/reference/android/os/AsyncTask

【讨论】:

  • 我收到一个空包
  • @user3761485 你也实现了服务器逻辑吗?你能告诉我们是谁在发送数据包,以便我们检查为什么它是空的吗?
【解决方案2】:

Android 官方文档

AsyncTask 允许正确且轻松地使用 UI 线程。此类允许您执行后台操作并在 UI 线程上发布结果,而无需操作线程和/或处理程序。

AsyncTask 被设计为围绕 Thread 和 Handler 的辅助类,并不构成通用的线程框架。 AsyncTasks 最好用于短时间的操作(最多几秒钟)。

改为创建自己的线程并将所有“网络相关”逻辑/代码放在那里。

    Thread thread = new Thread(){
        void run(){
           //put all your "network related code here"
        }
    }
    thread.start();

服务器代码也有助于理解问题。

【讨论】:

  • @Mehul 您能否分享一个官方文档链接来说明您提到的事实?我想知道,因为我已经大量使用 AsyncTask 进行网络通信而没有问题。我知道请求是按顺序执行的,直到我们提供一个外部执行器,但 doInBackground() 仍然在后台线程中执行,否则它会冻结 UI。
  • 我的理解是AsyncTask只是Thread类之上的一个辅助类/包装类,用来简化后台线程和主线程的同步,因为最后我们需要更新UI元素线程完成后,android也不允许从主线程以外的线程更新UI元素,以防止意外的内存泄漏。
  • @Hitesh Gupta 我已经编辑了答案并在引用中添加了文档。是的。我的直觉是这样的,因为我正在做一个项目,我曾经在 AsyncTask 中接收数据报包,这有时会导致 UI 冻结。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 2015-07-13
相关资源
最近更新 更多